【问题标题】:async: each function never completesasync:每个函数永远不会完成
【发布时间】:2020-10-08 03:15:00
【问题描述】:

我正在尝试使用async library 处理二维数组并处理每个展平项目。像这样:

import { each } from 'async';

let results: any[] = [];

await each(chats, async (chat) =>
    await each(chat.participants, async (participant) => {

        console.log('Before pause');
        // do something with participant
        results.push(fn(participant));
        await this.timeout(2500);
        console.log('After pause');

      })
);

console.log('Finished');

return results;

在哪里

let chats = [
  {
    participants: ['1', '2']
  },
  {
    participants: ['3', '4']
  }
]

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

但是,console.log('Finished') 永远不会执行。我在这段代码中尝试了很多asyncawait 的变体,但无法使其正常工作。我有一个使用纯异步/等待的工作版本,但想使用异步库。

我做错了什么?

请注意,我确实在不使用异步库的情况下使用 async/await 进行了这项工作,如下所示:

await Promise.all(chats.map(
  async (chat) =>
    await Promise.all(chat.participants
      .map(async (participant) => {

        console.log('Before pause');
        // do something with participant
        results.push(fn(participant));
        await this.timeout(2500);
        console.log('After pause');

      })
    )
));

return results;

但我想使用异步库,因为我希望使用该库中的其他函数。

【问题讨论】:

    标签: javascript typescript asynchronous async.js


    【解决方案1】:

    each() 的第二个参数采用以下形式:function(item, callback) {},每次迭代完成时都需要调用callback。请注意,这与 callbackeach() 的可选第三个参数不同。

    解决方案是每次迭代调用回调,如下所示:

    await each(chats, async (chat, done1 /*1️⃣*/) => {
    
      await each(chat.participants, async (participant, done2 /*2️⃣*/) => {
        //...
        done2(); /*3️⃣*/
      });
    
      done1(); /*4️⃣*/
    });
    
    console.log("Finished");
    

    demo

    【讨论】:

    • 遗憾的是这不起作用。您的演示中的console.log('Finished') 在异步函数内部,但在它需要的外部不起作用 - 我需要同步返回此函数的结果。
    【解决方案2】:

    试试这个

    let chats = [
      {
        participants: ['1', '2']
      },
      {
        participants: ['3', '4']
      }
    ]
    
    
    chats.forEach(chat =>
         chat.participants.forEach(async (participant) => {
    
            console.log('Before pause');
            // do something with participant
            await timeout(2500);
            console.log('After pause');
            console.log(participant)
    
          }));
    
    function timeout(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
    console.log('Finished');
    
    

    问题:-

    • await 仅适用于异步函数
    • 代替 this.timeout,在某些上下文中使用或直接在您的情况下使用。在 js here & here 中了解有关此行为的更多信息

    【讨论】:

    • OP 正在寻找一个明确使用 async 库的解决方案。 forEach 语句不平行。
    • 也看到了顶层等待。但他用 typescript 标记它,并且 typescript 3.8 有顶级等待(在模块中,这是一个)
    • 是的,正如@Titulum 所说,我想使用异步库,以便函数可以并行运行。 timeout() 正确地替代了我正在进行的异步 API 调用,
    • 好吧,在 js 中没有什么像并行(除非多个进程/线程正在运行),您只是将工作委派给下一个事件循环迭代。委托 for 循环是不好的,因为它是一个阻塞语句。在这种情况下,超时是应该委托的语句。除此之外,使用 Promise 的重点是避免回调。无论如何,如果您想将 for 循环执行委托给下一次迭代,可以使用 setImmediate 或 process.nextTick(谨慎使用 nextTick)。
    猜你喜欢
    • 2021-10-13
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    相关资源
    最近更新 更多