calling an async function inside for loop in JavaScript / node js

Viewed 6439

I want to call an async function inside for loop

function test(req,res){
 //somelogic part here
 
 async function create(data){
 //logic part here
 }
 
 for( var value in values){
  // some codeing part here
  await create(data);
  }
}
I am getting this error

uncaughtException: await is only valid in async function 

then I can't call an async function inside For loop. I know it is written like this but is there any possible way I can call an async function inside for loop

for await (var value in values)
7 Answers

Just put async in front of function test.

async function test(req, res) {…

If you want to await a promise, then the function that's using await needs to be async function.

Hi As I understood your concern I would suggest to use .map() function which is very useful in this type of case.

async function create(data) {
   // Create user logic here
}
const usernames = ['test1', 'test2', 'test3'];
const createdUsers = usernames.map(async (val) => {
    const user = await create();
    return user;
});

await Promise.all(createdUsers);

Wrap and create new function inside another function isn't a good ideal. You can move function create to outside like the code bellow

 async function create(data){
 //logic part here
 }
 
async function test(req,res){
 //somelogic part here

 for( var value in values){
  // some codeing part here
  await create(data);
  }
}

Or use arrow function instead

async function test(req,res){
 //somelogic part here
 const create = async (data) => {
 //logic part here
 }
 for( var value in values){
  // some codeing part here
  await create(data);
  }
}

The problem is not with your create function, but with your test function. The scope where you call the await syntax, needs to be async. Therefore, your scope here is test.

Simply update your code to the following;

/*vv --> async*/
async function test(req, res) {
  console.log("test is called");

  async function create(to) {
    return new Promise((resolve) => {
      setTimeout(() => resolve(Date.now()), to);
    });
  }

  const values = {
    a: 1e3,
    b: 2e3,
    c: 3e3
  };

  for (var value in values) {
    // some codeing part here
    const to = values[value];
    const result = await create(to);
    console.log("result:", result);
  }

  return 1;
}

(async() => {
  const res = await test();
  console.log("done");
})();

Your question is a little confusing because there doesn't appear to be any reason to async/await - create doesn't appear to return any data so the aync/await seems redundant, and you can probably remove it.

If, however, create does return a value, and you want to wait until all the values have been returned before you continue, create an array of function calls and then use Promise.all to wait until the promises returned from create have resolved.

// `create` returns a promise that resolves
// after two seconds
function create(data){
  return new Promise((res, rej) => {
    setTimeout(() => res(data), 2000);
  });
}


async function test(req,res) {
 const values = [1, 2, 3, 4];

 // Create an array of promises
 const arr = values.map(el => create(el));

 // And use Promise.all to wait to resolve them
 const output = await Promise.all(arr);
 console.log(output);
}

test();

If you put the Promise in the for loop then it will get a total of every responses time in every iteration. So I'm suggesting the Promise.all for that.

async func() {
    let arr = [];

    for(var value in values){
        arr.push(create(data));
    }

    let createdArr = await Promise.all(arr);

    // Using createdArr, you can get all waited responses
}

In here it will get only the most responding time, not the total. All Promises run at the same time.

Related