Search code examples
javascriptasync-awaitpromise

why new Promises get's used next to await while there is no need to them?


I had code below from javascript.info async/await tutorial and I noticed it has used new Promise next to await, this is the cut from the code:

await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();

link to code

so it's possible to type this code as below:

 await setTimeout(()=>{img.remove()}, 3000));

so I'm wondering what's the necessity to use new Promise next to await keyword(while we eliminate .then() and .catch() with await and try...catch but I've seen new Promises get used alongside the await)?

p.n: I thought maybe it gets used when we have conditions for rejection and success inside new Promise but in this example we have no condition and still it's used.


Solution

  • so it's possible to type this code as below:

    await setTimeout(()=>{img.remove()}, 3000));
    

    That is syntactically valid, but it's not going to do what you probably want. await only works with promises. setTimeout does not return a promise, it returns an id of the timeout. If you await something that isn't a promise the code will move on immediately1.

    So this will set up a timeout for 3 seconds, then move on to all the rest of your code. Any of that code that was expecting the image to have been removed will be operating under a false assumption and thus may have bugs.

    let removed = false
    function fakeRemove() { 
      console.log('removing')
      removed = true 
    }
    
    async function example () {
      console.log('before the await', removed);
      await setTimeout(() => { fakeRemove() }, 3000);
      console.log('after the await', removed);
    }
    
    example();

    Maybe you don't have any code that cares if the image has been removed, but in that case you can just do the timeout without await.

    In comparison, when you create the promise, now the await can be effective. All the code that comes after will be paused until those 3 seconds have elapsed

    let removed = false
    function fakeRemove() { 
      console.log('removing')
      removed = true 
    }
    
    async function example () {
      console.log('before the await', removed);
      await new Promise((resolve, reject) => setTimeout(resolve, 3000));
      fakeRemove()
      console.log('after the await', removed)
    }
    
    example()

    1) technically the await will queue up a microtask, and it must wait for that microtask to execute. But that just requires waiting for the remaining synchronous code in the call stack and other microtasks. It will not wait 3 seconds.