admin管理员组

文章数量:1425819

New to Angular, may be using promises wrong. I have a factory returning a promise:

.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;
}])

Now if I inject my factory somewhere I can use the promise:

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

This is fine, but I'm starting to use myData in several places and I don't want to be writing a new .then in every directive and controller I use the data in. After the promise is resolved I don't care about it anymore, is there any way to make myData return a promise if it's unresolved but return just the result after it's finished resolving?

To word it another way, can myData simple be the .then result after resolution, or do I have to write a new .then every time?

New to Angular, may be using promises wrong. I have a factory returning a promise:

.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;
}])

Now if I inject my factory somewhere I can use the promise:

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

This is fine, but I'm starting to use myData in several places and I don't want to be writing a new .then in every directive and controller I use the data in. After the promise is resolved I don't care about it anymore, is there any way to make myData return a promise if it's unresolved but return just the result after it's finished resolving?

To word it another way, can myData simple be the .then result after resolution, or do I have to write a new .then every time?

Share Improve this question asked Jan 20, 2015 at 19:49 diplosaurusdiplosaurus 2,5885 gold badges29 silver badges56 bronze badges 2
  • Do you have a default value that you could return instead of the value of the resolved promise? – Steve Mitcham Commented Jan 20, 2015 at 19:57
  • @SteveMitcham Sure, an empty object will do fine in this case. – diplosaurus Commented Jan 20, 2015 at 20:00
Add a ment  | 

2 Answers 2

Reset to default 5

On working with promises

First of all your myData service can just return the call:

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

Unwrapping values

So you know how to work with promises in Angular... But, you want something better, you want the promise to automatically unwrap with Angular's digests. This is tricky but it can be done. Note that it can be confusing in code and I don't really remend it but here's the general idea:

Automatic unwrapping

.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
}]);

This would let you do something like:

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

Which will put an empty array there and will replace it (also causing a digest) whenever the real data arrives, you can still do myData.then in order to check if it's done loading yourself so you can use the old syntax if you need to be sure.

Is it a good idea?

Note that Angular used to do this until version 1.2 (removed pletely in 1.3) but stopped doing so because automatic unwrapping was considered too magical. You can formulate your own decisions but take note that the Angular core team decided this was not a good idea. Note that things like ngResource still do this.

Yes, resolve the promise in your service/factory and reference the resolved promise value in your controllers instead of referencing and handling the promise in your controllers. Hope that makes sense.

本文标签: javascriptPromise factory in AngularStack Overflow