Patrioticcow
Patrioticcow

Reputation: 27038

how to resolve all promises in a for loop?

Yet another question about promises. I have this scenario:

Service.prototype.parse = function (data) {
    var deferred = $.Deferred();
    var arr      = [];
    for (var i = 0; i < data.length; i++) {
        var details = new Details();
        $.when(details).then(function (data) {
            arr.push(data);
            deferred.resolve(arr);
        });
    }

    return deferred.promise;
};

Somewhere else in the code:

...
$.when(parse()).then(function (resp) {
   //...
});

The promises get resolved at some point but initially resp has a length of 1.

How to wait for parse() to resolve everything and return a array?

Upvotes: 3

Views: 567

Answers (2)

JM Yang
JM Yang

Reputation: 1208

Please try this:

Service.prototype.parse = function(data) {
  var detailsArr = [];
  for (var i = 0; i < data.length; i++) {
    var details = new Details();
    detailsArr.push(details);
  }

  return $.when.apply($, detailsArr).then(function(){
    return Array.prototype.slice.call(arguments);
  });
};

Here we put all Details into an array, use $.when.apply($, arr) to wait for all Details get resolved. When it's done, each Details' return data will be passed to callback function as one parameter, so the call back function will receive total data.length number of parameters. Then we use Array.prototype.slice.call to convert all parameters to an array and return the result.

For your reference:

What does $.when.apply($, someArray) do?

How can I convert the "arguments" object to an array in JavaScript?

Upvotes: 0

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276286

No need for a deferred anti pattern (explicit construction) or for explicit array construction. Your code can be simplified to:

Service.prototype.parse = function (data) {
     return $.when.apply($, data.map(function(x){
         return new Details(); 
     }).then(function(){ return arguments; });//.then(Array.of); // instead, if want array
};

Some general advice:

  • You're ignoring the item you're iterating in the data, I assume you don't do that in your real code but just making sure.
  • It's generally not the best idea to perform async IO in a constructor. Please consider separating construction and initialization.
  • You should consider using native promises (or a library) or using jQuery 3.0.0 which supports non problematic promises.

Upvotes: 5

Related Questions