【问题标题】:Async with for and callback challenge:与 for 和回调挑战异步:
【发布时间】:2020-04-30 11:52:31
【问题描述】:

所以我花了好几个小时才让这个异步模式正常工作:

1) 我有一个异步功能准备消息,因为它需要下载附件

2) 我有一个函数发送消息,它调用 gmail api 并发送准备好的消息 此函数返回一个回调函数,我愿意在 onSuccess 上使用它

3) 我有一个循环调用这个 sendMessage 函数,它调用 preparemessage 函数

一切都按预期进行,循环创建 N 次调用和 N 个答案 然而,回调函数显然是之前配置的,并获得了 for 中最后一个值的结果。

这是代码的一部分:

arrayOfMessagesToBeSent=[{msg1},{msg2}...] (got from the store)

for (const x of arrayOfMessagesToBeSent) {

store.actions.gapi.sendMessage(
        await store.actions.mailing.prepareMsg(
          {messageStuf}     

        ),
        (answer) => {
        console.log("call:", x.id);
        store.actions.mailing.sendCallback(answer, x.id);
      };
      );

}

一旦准备消息完成,就会发送消息。每发送一封电子邮件,我都会得到一个有效的答复 但是 for 循环在后台继续运行并覆盖 x.id 值

store.actions.mailing.sendCallback(answer, x.id); => 答案遵循良好的通量 => 每条消息的答案都不同 => x.id 被覆盖,并且在执行此函数的所有时间,只获取 x.id

你知道我怎样才能同步它吗? 所以基本上我希望回调函数(或那个 x.id 变量)等到准备消息完成。

选项 A:最好的选项:在发送其他消息的同时准备好消息。这将是最好的解决方案

选项B:如果不可能,至少是助焊剂:

1) 准备 2) 发送 3) 回调,然后使用第二条消息 1) 准备 2) 发送 3) 回调...就足够了

注意:我不想将 promise-all 与 .map() 一起使用。我不想准备所有消息然后发送所有消息,循环 for 和选项 B 将是我的用例更好的实现。

谢谢!

【问题讨论】:

  • 你能显示你的实际代码吗? x 未在您的代码中定义。可能它是在导致standard closure in loop problem 的循环之外声明的,但我们只能猜测。
  • 我想知道“store.actions.gapi.sendMessage”是否也是异步的。并不是说它是或不是问题的一部分 - 但需要做更多的事情。
  • 实际上听起来您确实想使用Promise.allmap,这允许一次准备所有消息并在准备好后立即发送每条消息(而其他人仍在准备中),并等待一切最终完成。或者消息真的需要按顺序准备吗?在任何情况下,您都需要承诺 sendMessage,这样您就不必传递回调。

标签: javascript loops asynchronous async-await


【解决方案1】:

所以我想我可以使用 promise.all 获得选项 A。 我认为一旦所有的承诺都得到解决,这些函数就会执行......

但与此同时,感谢@​​Bergi,我已经解决了(选项 B)。只是承诺那个丑陋的回调,现在我可以像这样一步一步地做到这一点:

  const MSG = await store.actions.mailing.prepareMsg(
    {msg stuff}
  );
  const answer = await store.actions.gapi.sendMessagePromise(MSG);
  const doStuff = store.actions.mailing.sendCallback(answer, x.id);

在第一个消息已经发送之前没有准备好消息,但没关系:)

【讨论】: