Search code examples
javascriptes6-promise

Why doesnt Promise.all() work with async function?


I am exploring the use of Promise.all(), but I don't know why it doesn't give me expect result. I try to illustrate it step by step.

Let take a look of my code:

var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'foo');
});


var apiCall = async () =>{
    // to simulate a api call that will response after 5 sec 
     setTimeout(() => {return 1000}, 5000); 
    
}

Promise.all([p2,p3,apiCall()]).then(values => {
  console.log(values); // [3, 1337, undefine], but I expect  [3, 1337, 1000]
});

apiCall().then((response)=>{console.log(response)})

As my understanding, async function will immediately return a Promise, which is what Promise.all will wait for.

So I expect,

.then(values => {
  console.log(values); // [3, 1337, undefined]
});

will only execute after 5 sec.

But the output is like below in 2 sec already, and not [3, 1337, 1000]

undefined   
[ 1337, 'foo', undefined ]

I dont know where the problem lies, I expect

apiCall().then((response)=>{console.log(response)})

will give me "1000" instead of undefined


new edit

After gathering you guys answers, I tried this.

As my understanding, setTimeout is also a async, and it will automatically return a promise like any other promise.

So, based on this understanding, I write below code. but it doesnt work. I understand using Promise constructor will fix the problem. But I dont know what problem lies in this example

var apiCall = async () =>{
    // to simulate a api call that will response after 5 sec 
     const a = setTimeout(() => {return 1000}, 5000); 
    return a 
}

Solution

  • In short, you haven't done anything that would make apiCall wait for the timeout before resolving the promise.

    var apiCall = async () =>{
        // to simulate a api call that will response after 5 sec 
         setTimeout(() => {return 1000}, 5000);    
    }
    
    1. This is an async function so it return a promise.
    2. The first thing it does is call setTimeout
    3. Then it gets to the end without hitting a return statement so resolves the promise as undefined
    4. 5 seconds later the timeout finishes and calls the function passed to setTimeout. This function returns 1000. setTimeout doesn't do anything with the return value from the callback.

    To get a promise from a callback API (like setTimeout) you need to use new Promise (as you did for p3).

    The async keyword is only useful in that it allows you to use the await keyword. The fact it makes a the function return a promise should be thought of as a side effect needed to make await work.

    await is a tool for managing existing promises.