简体   繁体   中英

Trouble with Angular $q.all()

I have a factory which is making 'n' number of $http request and to fulfill this I am using $q.all() , so let me show you my factory code.

 app.factory('loadBooks',['$http','$q',function($http,$q){ var promises = []; return { getBooks : function(category,no){ for(var i =1; i<=no; i++){ var deferred = $q.defer(); console.log(i + 'request'); $http.get(`https://anapioficeandfire.com/api/${category}?page=${i}&pageSize=10`) .then(function(response){ deferred.resolve(response); console.log(response); }) .catch(function(response){ deferred.reject(response); }) promises.push(deferred); } return $q.all(promises); } } }]) 

And this is my controller from where i am calling the factory function

 app.controller('bookController',['$scope','loadBooks','$routeParams',function($scope,loadBooks,$routeParams){ $scope.count = $routeParams.no; loadBooks.getBooks('books',2).then(function(data){ $scope.books = data; }) .catch(function(response){ }); }]); 

Now the problem is I am making 2 request from the getBooks method and the api is sending me data for both the request but for some reason the first request pushes no data inside the promise array but the second does. I dont know what i am doing wrong. The api is working fine because I can see the data coming in my network tab but data from first request is not getting pushed inside the promise array! I would be thankful if you could tell me what the problem is. Btw I am new to $q.

You've fallen prey to an insidious bug called "closing over the loop variable". The value of the deferred variable changes in every iteration of the loop, so when this eventually executes:

deferred.resolve(response);

deferred is referring to the last value that the deferred variable took on.

On top of that, you're using the Explicit Promise Creation Antipattern, an antipattern that causes your promise code to be unnecessarily convoluted and error prone.

Solve both problems by using promises the way they're supposed to be used:

 app.factory('loadBooks', ['$http', '$q', function($http, $q) { return { getBooks: function(category, no) { var promises = []; for (var i = 1; i <= no; i++) { console.log(i + 'request'); promises.push( $http.get(`https://anapioficeandfire.com/api/${category}?page=${i}&pageSize=10`) ); } return $q.all(promises); } } }]) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM