首页 > 解决方案 > 带有等待异步问题的循环迭代

问题描述

我有一个带有两个等待异步函数的循环。我希望第二个函数(F2)会在第一个等待函数(F1)完成后触发。但是循环继续,甚至没有启动 F2。F2 仅在 F1 异步函数触发后触发。

我提供了跟踪功能来跟随流程。

        for (let i=0; i<5; i++){
        const S3result = (async () => {
          try {
            console.log ('starting await promise 1' );
            params.Key =  '012/' + 'bob1' + i.toString(); 
            await promiseS3(s3, params);
            console.log ('complete 1st upload');
            params.Key = '012/' +  'bob2' + i.toString();
            console.log ('starting await promise 2' );
            await promiseS3(s3, params);
            console.log('completed 2nd upload');

          } catch (e) {
            console.log (e)
          }
        })()



      const promiseS3 = (s3object,params)  => {
        return new Promise((resolve, reject) => {
            console.log ('start s3 Object promise function');
            s3object.upload(params, function(s3Err, data) { 
                if (s3Err) reject  ('bad S3 call')
            console.log(`File uploaded successfully at ${data.Location}`)
            resolve (data); 
            });

        })
      }

我预计 F1 会开火,等待,然后在 F1 完成后让 F2 开火。

这是输出:

启动await promise 1 start s3 对象promise函数 启动await promise 1 start s3 对象promise函数 启动await promise 1 start s3 对象promise函数 启动await promise 1 start s3 对象promise函数 启动await promise 1 start s3 函数后对象promise函数 文件上传成功在https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob14 完成第一次上传开始等待承诺 2 开始 s3 对象承诺功能文件在https://filesafe-beta.s3 成功上传。 us-west-1.wasabisys.com/012/bob11 完成第一次上传开始等待承诺 2 开始 s3 对象承诺功能文件在https://filesafe-beta.s3.us-west-1.wasabisys.com/012成功上传/鲍勃10 完成第 1 次上传开始等待承诺 2 开始 s3 对象承诺功能文件成功上传到https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob12 完成第一次上传开始等待承诺 2 开始 s3 对象承诺function 文件在https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob13上传成功 完成第一次上传开始等待承诺 2 开始 s3 对象承诺功能文件在https://filesafe-成功上传beta.s3.us-west-1.wasabisys.com/012/bob22 完成第二次上传 文件上传成功在https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob21 完成第二次上传文件在https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob23成功上传 完成第二次上传 文件成功上传至https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob24 完成第二次上传 文件成功上传至https://filesafe-beta.s3.us-west -1.wasabisys.com/012/bob20 完成第二次上传

标签: node.jsamazon-s3async-await

解决方案


你必须把async上面的for循环,而不是for循环内。请记住,一旦async函数命中 an await,它就会立即返回一个 Promise。因此,按照您的结构方式,您根本不会暂停for循环。您只是在创建一个异步函数并在循环的每次迭代中一遍又一遍地执行它,而没有人关注async函数返回的承诺。

所以,你可以这样做:

const S3result = (async () => {
   for (let i=0; i<5; i++){
      try {
        console.log ('starting await promise 1' );
        params.Key =  '012/' + 'bob1' + i.toString(); 
        await promiseS3(s3, params);
        console.log ('complete 1st upload');
        params.Key = '012/' +  'bob2' + i.toString();
        console.log ('starting await promise 2' );
        await promiseS3(s3, params);
        console.log('completed 2nd upload');

      } catch (e) {
        console.log (e)
      }
    }
 })()

此外,S3result将是一个承诺,当for循环和其中的所有await语句都完成时,该承诺将被解决。


或者,像这样,您实际上是在正确的循环视图中函数await的结果,所以它实际上会暂停循环(这个循环本身必须在一个函数中才能使用,所以这里可能没有理由使用 IIFE . 让循环像第一个选项一样直接管理语句可能更简单:asyncforforforasyncawaitforawait

async function someFunction() {
    for (let i=0; i<5; i++){
        await (async () => {
          try {
            console.log ('starting await promise 1' );
            params.Key =  '012/' + 'bob1' + i.toString(); 
            await promiseS3(s3, params);
            console.log ('complete 1st upload');
            params.Key = '012/' +  'bob2' + i.toString();
            console.log ('starting await promise 2' );
            await promiseS3(s3, params);
            console.log('completed 2nd upload');

          } catch (e) {
            console.log (e)
          }
        })();
     }
}

推荐阅读