2013-09-11 6 views
28

У меня есть следующий код: angularjsОжидание обещания?

$scope.clients = commonFactory.getData(clientFactory.getClients()); 
if ($scope.clients.length > 0) { 
    $scope.sampleForm.ClientId = $scope.clients[0].ClientId; 
} 

и функция GetData в commonFactory:

factory.getData = function (method) { 
    method.then(function (response) { 
     return response.data; 
    }, function (error) { 
     $rootScope.alerts.push({ type: 'error', msg: error.data.ExceptionMessage }); 
    }); 
}; 

Проблема заключается в том, что $ scope.clients.length не определен, когда она попадает этой линии из-за асинхронный вызов.

Есть ли способ не проверять длину, пока не узнаю, что $ scope.clients назначен? Я смотрел на что-то вроде этого:

$scope.clients = commonFactory.getData(clientFactory.getClients()).then(function() { 
    if ($scope.clients.length > 0) { 
     $scope.sampleForm.ClientId = $scope.clients[0].ClientId; 
    } 
}); 

Попытка цепи мои then обещания, но не кости ... цель здесь не иметь метод GetData, чтобы избежать кучу шаблонного кода для ловли ошибок .. Возможно, я собираюсь сделать это неправильно?

+0

Я обновил свой ответ с помощью живой демоверсии. Дайте знать, если у вас появятся вопросы. – m59

+0

@ m59 вопрос ниже :) – Nicros

ответ

34

Это самая простая ситуация, для которой обещают. Вам просто нужно сделать обещание с var deferred = $q.defer() при начале операции async, разрешить обещание с deferred.resolve(result), когда операция async завершена, и верните deferred.promise в вашу функцию. Асинхронные методы Angular делают это внутренне и возвращают обещания уже, поэтому вы можете просто вернуть те же обещания, а не создавать новые обещания с $q.defer(). Вы можете прикрепить .then ко всему, что возвращает обещание. Кроме того, если вы возвращаете значение из then функции, это значение будет вставлено в обещание, так что then цепь может продолжать

angular.module('myApp', []) 

.factory('myService', function($q, $timeout, $http) { 
    return { 
    myMethod: function() { 
     // return the same promise that $http.get returns 
     return $http.get('some/url'); 
    } 
    }; 
}) 

.controller('myCtrl', function($scope, myService) { 
    myService.myMethod().then(function(resp) { 
    $scope.result = resp.data; 
    }); 
}) 

А вот немного больше удовольствия с цепочкой:

.factory('myService', function($q, $timeout, $http) { 
    return { 
    myMethod: function() { 
     // return the same promise that $http.get returns 
     return $http.get('some/url').then(function() { 
     return 'abc'; 
     }); 
    } 
    }; 
}) 

.controller('myCtrl', function($scope, myService) { 
    myService.myMethod().then(function(result) { 
    console.log(result); // 'abc' 
    return someOtherAsyncFunc(); // for example, say this returns '123' 
    }).then(function(result) { 
    console.log(result); // '123' 
    }); 
}) 
+0

Это потрясающая благодарность. Один вопрос, хотя, хотя я заметил, что в моем примере правильно задано значение $ scope.clients, вызов установить ClientId из $ scope.clients [0] .ClientId не работает. Так что немного назад к оригинальной проблеме ...? – Nicros

+0

@Nicros У вас будут проблемы, подобные этому, пока вы не поймете, как подойти к вещам с угловатым. Ваш код повсюду. Если вы сделаете живую демонстрацию своего кода, я смогу помочь лучше ее очистить. Мне нужно на самом деле те «методы», которые упомянуты в вашем коде. – m59

+0

[обновлено JSBin] (http://jsbin.com/iCaDIVi/6/edit) Ух, когда я удаляю «длину», ваш код работает :) у меня все еще нет. Будет работать на лучший пример и обновить его ... не могу сделать это до конца, хотя ... – Nicros

Смежные вопросы