1

I am attempting to write an async function that makes multiple fetches, waits for all to complete, then returns the JSON results as an array. This is what I have so far:

file1.js

const searchResults = await Api.search(searchText);

api.js

async function search(searchText) {
    return util.executeFetchAll([
        `/searchA/${searchText}`,
        `/searchB/${searchText}`,
        `/searchC/${searchText}`
    ]);
}

util.js

async function executeFetchAll(urls) {
    const promises = urls.map(url => fetch(url));
    const responses = await Promise.all(promises);

    debugger;
}

When execution pauses at the debugger and I inspect responses using Chrome's dev tools, it is correctly an array of 3 Response objects, but if I inspect responses[0].json(), it weirdly returns in the console a Promise {<pending>} object.

What am I missing? I'm awaiting Promise.all, which should mean all promises resolve before my debugger line. So why is the json() method weirdly showing a Promise object in a pending state?

Thanks.

Matt
  • 23,363
  • 39
  • 111
  • 152

1 Answers1

3

response.json() return a Promise! see: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

So you can await them with something like this:

await Promise.all(responses.map(r => r.json()));
nem035
  • 34,790
  • 6
  • 87
  • 99
  • Thanks. But I guess I'm wondering why the promises would still be pending at all following my call to `await Promise.all(...)`. Why on the next line, where we hit the debugger, would they still be showing as pending? Shouldn't they be resolved by the time the await line is finished? – Matt Sep 28 '18 at 14:39
  • Also, sorry, I just noticed, I'm trying to **assign** Promise.all to `responses`, but you're using `responses` in Promise.all, as an argument. Can you clarify, in context of my code example, the order of execution? Thanks. – Matt Sep 28 '18 at 14:43
  • First, you wait for a response from the server (fetch) then you wait for the conversion of the payload from json (.json). Both return functions return a promise. Let me rewrote my example to help you: `const responses = await Promise.all(promises); const jsonPromises = responses.map(r => r.json()); const objects = await Promise.all(jsonPromises); ` – Damien Gilles Sep 28 '18 at 14:45
  • Thank you for rewriting! – Matt Sep 28 '18 at 14:46
  • Tried your updated example from your previous comment, but `objects` ends up being: `[false, false, false]`. – Matt Sep 28 '18 at 15:02
  • I tested the code with a simple API `urls = ['https://jsonplaceholder.typicode.com/todos/1', 'https://jsonplaceholder.typicode.com/todos/1', 'https://jsonplaceholder.typicode.com/todos/1'];` and it works. Your api returns probably false. Use the network tab of the developer console to see what the server sent you. – Damien Gilles Sep 28 '18 at 15:11
  • You're right. I assumed my API was returning the right values. Bad assumption. So this is working. Even so, I'm still confused about `responses` not having 3 resolved promises after `await Promise.all(...)`. Why are they still pending, such that I'd have to `await` a **second** time? – Matt Sep 28 '18 at 15:38