How to wait for AsyncRequests for each element from an array using reduce and promises

夙愿已清 提交于 2020-01-17 04:51:07

问题


I'm new on AngularJS and JavaScript.

I am getting remote information for each of the elements of an array (cars) and creating a new array (interested prospects). So I need to sync the requests. I need the responses of each request to be added in the new array in the same order of the cars.

I did it first in with a for:

for (a in cars) {
    //async request
    .then(function () {
        //update the new array
    });
}

This make all the requests but naturally didn't update the new array.

After seeking in forums, I found this great examples and explanations for returning a intermediate promise and sync all of them.

1. http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html
 2. http://stackoverflow.com/questions/25605215/return-a-promise-from-inside-a-for-loop 
 3. http://www.html5rocks.com/en/tutorials/es6/promises/

(@MaurizioIndenmark, @Mark Rajcok , @Michelle Tilley, @Nolan Lawson)

I couldn't use the Promise.resolve() suggested in the second reference. So I had used $q.defer() and resolve(). I guess I have to inject a dependency or something else that I missed. As shown below:

In the Controller I have:

$scope.interestedProspects = [] ;

RequestDetailsOfAsync = function ($scope) {
    var deferred = $q.defer();
    var id = carLists.map(function (car) {
        return car.id;
    }).reduce(function (previousValue, currentValue) {
        return previousValue.then(function () {
            TheService.AsyncRequest(currentValue).then(function (rData) {
                $scope.interestedProspects.push(rData);
            });
        });
    }, deferred.resolve());
};

In the Service I have something like:

angular.module('app', []).factory('TheService', function ($http) {
    return {
        AsyncRequest = function (keyID) {
            var deferred = $q.defer();
            var promise = authorized.get("somep.provider.api/theService.json?" + keyID).done(function (data) {
                deferred.resolve(data);
            }).fail(function (err) {
                deferred.reject(err);
            });
            return deferred.promise;
        }
    }
}

The displayed error I got: Uncaught TypeError: previousValue.then is not a function

I made a jsfiddle reusing others available, so that it could be easier to solve this http://jsfiddle.net/alisatest/pf31g36y/3/. How to wait for AsyncRequests for each element from an array using reduce and promises

I don't know if the mistakes are:

  • the place where the resolve is placed in the controller function.
  • the way the reduce function is used

The previousValue and currentValue sometimes are seen by javascript like type of Promise initially and then as a number. In the jsfiddle I have a working example of the use of the reduce and an http request for the example.


回答1:


Look at this pattern for what you want to do:

        cars.reduce(function(promise, car) {
            return promise.then(function(){
              return TheService.AsyncRequest(car).then(function (rData) {
                $scope.details.push(rData);
              });
            });
        }, $q.when());

This will do all the asynchronous calls for every car exactly in the sequence they are in the cars array. $q.all may also be sufficient if the order the async calls are made doesn't matter.




回答2:


It seems you are calling reduce on an array of ids, but assume in the passed function that you are dealing with promises.

In general, when you want to sync a set of promises, you can use $q.all

You pass an array of promises and get another promise in return that will be resolved with an array of results.



来源:https://stackoverflow.com/questions/34115441/how-to-wait-for-asyncrequests-for-each-element-from-an-array-using-reduce-and-pr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!