循环迭代与等待异步问题

时间:2019-08-13 21:27:40

标签: node.js amazon-s3 async-await

我有两个等待异步功能的循环。我希望第二个函数(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完成后开火。

这是输出:

开始等待承诺1 启动s3对象承诺函数 开始等待诺言1 启动s3对象承诺函数 开始等待诺言1 启动s3对象承诺函数 开始等待诺言1 启动s3对象承诺函数 开始等待诺言1 启动s3对象承诺函数 后功能 文件已成功上传到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/bob10 完成第一次上传 开始等待诺言2 启动s3对象承诺函数 文件已成功上传到https://filesafe-beta.s3.us-west-1.wasabisys.com/012/bob12 完成第一次上传 开始等待诺言2 启动s3对象承诺函数 文件已成功上传到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 完成第二次上传

2 个答案:

答案 0 :(得分:2)

您必须将async放在for循环上方,而不是放在for循环内。请记住,一旦async函数击中await,它就会立即返回一个承诺。因此,按照它的结构方式,您根本不需要暂停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循环的正确视图中实际async函数的结果for,因此实际上将暂停for循环(此for循环本身必须在async函数中才能使用await,因此在这里可能没有理由使用IIFE。让for循环管理{与第一种选择一样,直接使用{1}}语句可能更简单:

await

答案 1 :(得分:1)

问题在于,所有这些for循环所要做的就是创建一个异步函数并立即执行它。因此,可以将其视为同时在for循环内分解5个不同的函数实例。

这就是为什么您没有按特定顺序返回结果的原因。以文件名的最后一位数字表示,功能已完成:14、11、10、12、13、22、21、23、24、20,而我认为您期望的是10、20、11、21 、。 .. 14,24。

要解决此问题,请摆脱以下几行:

  <EntityType Name="Person" OpenType="true">
   <Key>
       <PropertyRef Name="UserName" />
   </Key>

const S3result = (async () => {