Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Promise.all [duplicate]

One of the exercises in Chapter 17 of the book Eloquent Javascript is to implement the Promise.all() method, I came up with this implementation (which doesn't work):

function all(promises) {
  return new Promise(function(success, fail) {
    var successArr = new Array(promises.length);
    if (promises.length == 0)
      success(successArr);
    var pending = promises.length;
    for (var i = 0; i < promises.length; i++) {
      promises[i].then(function(result) {
        successArr[i] = result;
        pending -= 1;
        if (pending == 0)
          success(successArr);
      }, function(error) {
        fail(error);
      });
    }
  });
}


// Testing
function soon(val) {
  return new Promise(function(success) {
    setTimeout(function() { success(val); },
               Math.random() * 500);
  });
}
all([soon(1), soon(2), soon(3)]).then(function(array) {
  console.log("This should be [1, 2, 3]:", array);
});
// => [undefined, undefined, undefined, 3]

Interestingly, the author's solution is similar apart from the use of forEach to iterate over the promises array instead of the for loop in my case:

function all(promises) {
  return new Promise(function(success, fail) {
    var successArr = new Array(promises.length);
    if (promises.length == 0)
      success(successArr);
    var pending = promises.length;
    promises.forEach(function(promise, i) {
      promise.then(function(result) {
        successArr[i] = result;
        pending -= 1;
        if (pending == 0)
          success(successArr);
      }, function(error) {
        fail(error);
      });
    });
  });
}

// Testing
function soon(val) {
  return new Promise(function(success) {
    setTimeout(function() { success(val); },
               Math.random() * 500);
  });
}
all([soon(1), soon(2), soon(3)]).then(function(array) {
  console.log("This should be [1, 2, 3]:", array);
});
// => [1, 2, 3]

Why does the use forEach makes all the difference here?, I'm guessing it's something related to the scope created by the anonymous function passed to forEach, but I can't quite figure how that works.

like image 927
Edmeral Avatar asked Apr 10 '16 14:04

Edmeral


People also ask

Does promise all wait for all promises?

Promise.all waits for all fulfillments (or the first rejection).

What happens if you resolve a promise twice?

No. It is not safe to resolve/reject promise multiple times. It is basically a bug, that is hard to catch, becasue it can be not always reproducible.

Does promise all run promises in parallel?

As you can see, Promise. all executes code concurrently, but what is parallel execution? JavaScript is single-threaded and can only perform a single chunk of work at a time, so parallel execution is not possible with JavaScript, except for some circumstances such as web workers.

Does promise all run sequential?

In this approach, we will use Promise. allSettled() which will be executed in a quite similar manner as Promise. all() method executed by taking promises as input in the single array and executing them sequentially.


1 Answers

I just figured it out, it's the i variable, because we're on a for loop, it changes before the promise get a chance to resolve but on the forEach version the i variable is properly scoped so each iteration has it's own i variable

like image 58
Edmeral Avatar answered Nov 13 '22 20:11

Edmeral