Фабрика обещаний в Angular

Новичок в Angular, может неправильно использовать промисы. У меня есть фабрика, возвращающая обещание:

.factory('myData', ['$http', '$q', function($http, $q) {
    var deferred = $q.defer();

    $http.get('/path/to/endpoint')
        .success(function(data) {
            deferred.resolve(data);
        })
        .error(function(err) {
            deferred.reject(err.what())
        });

    return deferred.promise;
}])

Теперь, если я куда-нибудь добавлю свою фабрику, я могу использовать обещание:

.controller('myController', ['$scope', 'myData', function($scope, myData) {
    myData.then(function(result) {
        $scope.data = result;
    });
}]);

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

Другими словами, может ли myData simple быть .then result после разрешения, или мне нужно каждый раз писать новое .then?


person diplosaurus    schedule 20.01.2015    source источник
comment
У вас есть значение по умолчанию, которое вы могли бы вернуть вместо значения разрешенного обещания?   -  person Steve Mitcham    schedule 20.01.2015
comment
@SteveMitcham Конечно, в этом случае пустой объект подойдет.   -  person diplosaurus    schedule 20.01.2015


Ответы (2)


О работе с обещаниями

Прежде всего, ваша служба myData может просто вернуть вызов:

.factory('myData', ['$http', function($http) {
    return $http.get('/path/to/endpoint').then(function(req){
       return req.data;
    });
}]);

Разворачивание значений

Итак, вы знаете, как работать с промисами в Angular... Но вы хотите чего-то лучшего, вы хотите, чтобы промис автоматически разворачивался с дайджестами Angular. Это сложно, но это можно сделать. Обратите внимание, что это может сбивать с толку в коде, и я не очень рекомендую это, но вот общая идея:

Автоматическая распаковка

.factory('myData', ['$http', function($http) {
    var result = []; // initial result to return
    var p = $http.get('/path/to/endpoint').then(function(res){
       result.push.apply(result, res.data); // add all the items
    });
    result.then = p.then; // allow hooking on it
    return result; // return the array, initially empty
}]);

Это позволит вам сделать что-то вроде:

.controller('myController', ['$scope', 'myData', function($scope, myData) {
    $scope.data = myData;
}]);

Что поместит туда пустой массив и заменит его (также вызывая дайджест) всякий раз, когда поступают реальные данные, вы все равно можете сделать myData.then, чтобы проверить, завершена ли загрузка самостоятельно, чтобы вы могли использовать старый синтаксис, если вам нужно быть уверенным .

Это хорошая идея?

Обратите внимание, что Angular делал это до версии 1.2 (полностью удалено в 1.3), но прекратил это делать, потому что автоматическое развертывание считалось слишком волшебным. Вы можете сформулировать свои собственные решения, но учтите, что основная команда Angular решила, что это не очень хорошая идея. Обратите внимание, что такие вещи, как ngResource, все еще делают это.

person Benjamin Gruenbaum    schedule 20.01.2015

Да, разрешайте обещание в своей службе/фабрике и ссылайтесь на разрешенное значение обещания в своих контроллерах вместо того, чтобы ссылаться и обрабатывать обещание в своих контроллерах. Надеюсь, это имеет смысл.

person Patrick Motard    schedule 20.01.2015
comment
Вроде, как бы, что-то вроде. Как мне указать только значение обещания, а не само обещание? - person diplosaurus; 20.01.2015