Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call await in a callback inside an async function

Here is some code (it's an over-simplified example, I know it is dumb):

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function test() {
    [1, 2, 3].map(() => {
        console.log('test');
        await sleep(1000);
    });
}
test();

The objective is to:

  1. display test then wait one second
  2. then display test then wait one second
  3. then display test then wait one second

But running this code results in a failure:

await is a reserved word

I know I can do fix it by using a for loop:

async function test() {
    for(let i = 0; i < 3; i++) {
        console.log('test');
        await sleep(1000);
    }
}

But is there a way to do it in a more "functional" way. I mean, can I avoid the for loop and await inside a map?

like image 535
rap-2-h Avatar asked Jun 15 '17 13:06

rap-2-h


People also ask

Can we use async await with callback?

The await keyword is used in an async function to ensure that all promises returned in the async function are synchronized, ie. they wait for each other. Await eliminates the use of callbacks in . then() and .

Can we use await for async function?

If the functions in your example are synchronous, then adding await has no effect whatsoever. The function is called, and when it returns, execution continues.

Can callbacks and promises be used together for async operations?

The async function declaration defines an asynchronous function, which returns an AsyncFunction object. Async/await is actually built on top of promises. It cannot be used with plain callbacks or node callbacks. The word “async” before a function means one simple thing: a function always returns a promise.

Can I use await inside for?

for await...of can only be used in contexts where await can be used, which includes inside an async function body and in a module. Even when the iterable is sync, the loop still awaits the return value for every iteration, leading to slower execution due to repeated promise unwrapping.


2 Answers

const result = await [1, 2, 3].reduce(async function(prom, v){   
    const result= await prom;
    await sleep(1000);
    result.push(v);
    return result;
 }, Promise.resolve([]));

You could reduce to create a promise chain. However in your simplyfied case:

(a=b=>(b==2||(console.log("test"),setTimeout(a,1000,b+1))))(0);
like image 71
Jonas Wilms Avatar answered Oct 20 '22 05:10

Jonas Wilms


If a library like bluebird is an option then you could write:

'use strict'
const Promise = require('bluebird')


async function test() {
  return Promise.mapSeries([1, 2, 3], async (idx) => {
    console.log('test: ' + idx);
    await Promise.delay(1000)
  });
}
test();
like image 22
t.niese Avatar answered Oct 20 '22 05:10

t.niese