1

I'm newer to node.js and writing a program that is going to require promises for async API calls. I have a question regarding the execution of some example code that I have stumbled across in my research.

The code below (from my understanding) will hit an API, wait for the response, then resolve that response as a promise. This is done iteratively and every created promise is passed into an array of promises. Eventually Promise.all() is called on the array of promises and .then() more code will execute to iterate over the array and add the image to the page.

function getMovie(title) {
  return new Promise(function(resolve, reject) {
  var request = new XMLHttpRequest();

  request.open('GET', 'http://mymovieapi.com/?q=' + title);
  request.onload = function() {
    if (request.status == 200) {
    resolve(request.response); // we get the data here, so resolve the Promise
    } else {
      reject(Error(request.statusText)); // if status is not 200 OK, reject.
    }
  };

    request.onerror = function() {
      reject(Error("Error fetching data.")); // error occurred, so reject the Promise
    };

    request.send(); // send the request
 });
}

function fetchMovies() {
  var titles = document.getElementById('titles').value.split(',');
  var promises = [];

  for (var i in titles) {
    promises.push(getMovie(titles[i])); // push the Promises to our array
  }

  Promise.all(promises).then(function(dataArr) {
    dataArr.forEach(function(data) {
    var img = JSON.parse(data)[0].poster.imdb;

    document.getElementById('movies').innerHTML =      document.getElementById('movies').innerHTML + '<img src="' + img + '"/>';
    });
  }).catch(function(err) {
    console.log(err);
  });
};
fetchMovies();

What I'm not understanding here is how Promise.all() waits for ALL of the API responses to be pushed into promises. Since getMovie(title) resolves every promise before it is pushed into the promises array, shouldn't it be the case that the first resolved promised that is pushed in causes the Promise.all() section to execute (as 1 of 1 promises in the array are resolved)?

Scott
  • 422
  • 1
  • 4
  • 17
  • How many times `Promise.all(promises)` line is invoked? How many items it has in its parameter array when it happens? Answer these questions and you'll be enlightened. ) – raina77ow Sep 13 '16 at 17:18
  • 2
    I think you misunderstand what promises are doing. The promise object is created immediately and the closure is passed back through the thenable. The invocation of the chain happens synchronously - but the resolves evaluate one after the other. Within the all - each promise added to the collection evaluates the state of the collection at resolution. When all of them resolve the state shifts to a resolved state and the contents of the array -- the results of that first getMedia function -- is passed in. – Scott Fanetti Sep 13 '16 at 17:21
  • hi scott, If you understand mongoose, perhaps this link might help http://stackoverflow.com/questions/39470090/node-js-detect-when-two-mongoose-find-are-finished/39471376#39471376 – vdj4y Sep 13 '16 at 17:32

2 Answers2

3

I think the confusion comes where you say "Since getMovie(title) resolves every promise before it is pushed into the promises array".

This is not what is happening. Notice the return statement. The getMovie function returns a Promise object immediately, and resolves when the resolve (or reject) function is called at some later time (typically), in this case after an asynchronous call.

So it first returns a promise, then at a later time the promise resolves (or rejects). And Promise.all waits for an array of these promises to resolve.

aw04
  • 10,857
  • 10
  • 56
  • 89
0

By the time you call Promise.all, the array has been filled with the Promise objects. Promise.all does the equivalent of calling .then on all of the promises. When all of the promises are resolved, or one rejects, your handlers get called.

Jed Fox
  • 2,979
  • 5
  • 28
  • 38