Search code examples
javascriptes6-promise

Promise.all resolving prematurely


I want to fetch multiple JSON files. Here's my code:

var timestamps = [];
var urls = ['assets/layouts/default.json','assets/layouts/simple.json'];
var jsons = [];
Promise.all(urls.map(url => {
  fetch(url)
  .then(data => data.json())
  .then(json => {
    jsons.push(json);
    timestamps.push(performance.now());
  });
}))
.then(() => {
  console.log(`All assets loaded. Assets were loaded at: ${timestamps}, this log was made at ${performance.now()}. Loaded data: ${jsons}`);
}
);

The problem is that the Promise.all seems to resolve prematurely. As you can see I included some debugging, it logs this:

All assets loaded. Assets were loaded at: , this log was made at 37.73. Loaded data: 

If I wrap that console.log in a setTimeout and save the time when Promise.all is resolved like so:

.then(() => {
  let promiseResolvedAt = performance.now();
  setTimeout(() => {
    console.log(`All assets loaded. Assets were loaded at: ${timestamps}, Promise.all was resolved at ${promiseResolvedAt}. Loaded data: ${jsons}`);
  })
}

I get this:

All assets loaded. Assets were loaded at: 63.44000000000001,63.555, Promise.all was resolved at 55.96500000000001. Loaded data: [object Object],[object Object]

I can get it to work like I want it to by using setTimeout but I'm sure there is a better way and I'm just doing something wrong here.

Why does the Promise.all resolve before it's component promises resolve?

I'm running this on Chrome 55.


Solution

  • You need to return the promise:

    Promise.all(urls.map(url => {
      return fetch(url)
        .then(data => data.json())
        .then(json => {
          jsons.push(json);
          timestamps.push(performance.now());
        });
    }))
    

    From https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Function_body:

    Arrow functions can have either a "concise body" or the usual "block body".

    In a concise body, only an expression is needed, and an implicit return is attached. In a block body, you must use an explicit return statement.