【问题标题】:calling an async function inside for loop in JavaScript / node js在 JavaScript / 节点 js 中的 for 循环内调用异步函数
【发布时间】:2021-09-11 07:37:06
【问题描述】:

我想在 for 循环中调用一个异步函数

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);
  }
}
我收到此错误
uncaughtException: await is only valid in async function 

那么我不能在 For 循环中调用异步函数。 我知道它是这样写的,但是有什么方法可以在 for 循环中调用异步函数

for await (var value in values)

【问题讨论】:

  • 将 for 循环放入 async 函数中。此外,错误清楚地表明了这一点。它只能在异步内部工作
  • 除非create 返回一个值,否则我认为没有理由在这里使用async/await

标签: javascript node.js for-loop


【解决方案1】:

只需将async 放在功能测试前面即可。

async function test(req, res) {…

如果你想await一个promise,那么使用await的函数必须是async函数。

【讨论】:

  • 它的说法 await 仅在异步函数中有效
  • 除非你的括号放错了地方,否则函数测试包含函数创建和for循环。如果这是正确的,那么将 test 设为 async 函数将让您在 for 循环中使用 await ,该循环位于函数测试中。
【解决方案2】:

您好,正如我理解您的担忧,我建议使用 .map() 函数,该函数在这种情况下非常有用。

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);

【讨论】:

    【解决方案3】:

    如果只调用一个异步函数只是 for 循环的一部分,则意味着您可以简单地将异步调用返回的 promise 推送到数组并使用 promise 静态方法,如“all”

    let pros= []
    for(){
        pro.push(create(data));
    }
    Promise.all(pros).then(()=> {
        #implement rest or resolve another promise
    })
    

    请参考.. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

    【讨论】:

      【解决方案4】:

      在另一个函数中包装和创建新函数并不是一个好的理想。您可以像下面的代码一样将函数创建移动到外部

       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);
        }
      }
      

      或者用箭头函数代替

      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);
        }
      }
      

      【讨论】:

      • 另外,为什么箭头函数是个好主意?
      【解决方案5】:

      问题不在于您的create 函数,而在于您的test 函数。您调用await 语法的范围必须是async。因此,您的范围是test

      只需将您的代码更新为以下内容;

      /*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");
      })();

      【讨论】:

      • 我也试过了,仍然出现同样的错误error: uncaughtException: await is only valid in async function
      • @Vikas 那么问题是你调用test函数。它的范围是异步的吗?我已经更新了代码,以便为您提供代码模型的简短示例。
      【解决方案6】:

      您的问题有点令人困惑,因为 async/await 似乎没有任何理由 - create 似乎没有返回任何数据,因此 aync/await 似乎是多余的,您可以将其删除。

      但是,如果 create 确实返回了一个值,并且您想等到所有值都返回后再继续,请创建一个函数调用数组,然后使用 Promise.all 等待从create 已解决。

      // `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();

      【讨论】:

        【解决方案7】:

        如果您将Promise 放在for loop 中,那么它将在每次迭代中获得每个响应时间的总和。所以我建议Promise.all

        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
        }
        

        在这里它只会得到最多的响应时间,而不是总数。所有Promises 同时运行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-16
          • 2012-10-31
          • 1970-01-01
          • 2015-11-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多