1

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.

ngr900
  • 452
  • 4
  • 12

2 Answers2

1

You need to return the calls to fetch when mapping the array of URLs, otherwise your Promise.all(...) is waiting on [undefined, undefined], which will resolve immediately, as you observed.

Promise.all(urls.map(url => {
   return fetch(url)
// ^^^^^^
    .then(data => data.json())
    .then(json => {
      jsons.push(json);
      timestamps.push(performance.now());
    });
}))
sdgluck
  • 24,894
  • 8
  • 75
  • 90
1

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.

sp00m
  • 47,968
  • 31
  • 142
  • 252