我可以使用 async/await 来等待 JavaScript 中的多个事件吗?

Posted

技术标签:

【中文标题】我可以使用 async/await 来等待 JavaScript 中的多个事件吗?【英文标题】:Can I use async/await to wait for multiple events in JavaScript? 【发布时间】:2017-09-30 12:33:21 【问题描述】:

考虑以下情况:

const waitForEvent = async (api) => 
  api.on('eventOne', () => 
    return 'eventOne';
  )


  api.on('eventTwo', () => 
    return 'eventTwo';
  )


  api.on('eventThree', () => 
    return 'eventThree';
  )

  api.load();

我要做的是在异步函数内的api 变量上设置事件回调,触发api.load() 函数,然后返回首先发生的事件,在这种情况下是eventOne|eventTwo|eventThree

问题是,这个语法不好,这个例子不起作用。我找不到任何方法来使用 async/await 来实现这一点,不得不恢复到这样的承诺:

const waitForEvent = (api) => 
  return new Promise(resolve) => 
    api.on('eventOne', () => 
      resolve('eventOne');
    )


    api.on('eventTwo', () => 
      resolve('eventTwo');
    )


    api.on('eventThree', () => 
      resolve('eventThree');
    )

    api.load();
  

所以我的问题是,这可以使用 async/await 来完成吗?无论如何,这可以使用新的 async/await es7 语法来完成吗?

【问题讨论】:

一个问题是您的return 语句从它们的特定事件处理函数返回它们的值,而不是主要的waitForEvent 函数 当然,我知道 :) 感谢您指出这一点。我正在想办法解决这个问题。 我不明白你所说的“我不得不恢复承诺”是什么意思。 async/await 仍然使用承诺?而如果api没有被promisified,则需要使用Promise构造函数。 eventOne、eventTwo、eventThree是什么意思?是“其中一个”还是“任意数量的任意顺序”或“所有 3 个随机顺序”?我问是因为也许 Promise 不是解决您的问题的最佳抽象。 【参考方案1】:

由于async/await 允许我们以同步的方式(词法自上而下)编写异步构造,因此实际上并没有一种特定的方法可以同时执行 3 行不同的代码(或更准确地说,语句)。

最理想的 api 是 Promise.race

首先你将你的 api 回调转换为返回一个承诺:

const apiPromiseBuilder = (api) => (eventName) => new Promise(resolve => api.on(eventName, () => 
  resolve(eventName);
));

然后你参加你需要的所有赛事:

const waitForEvent = (api) => 

  const apiPromise = apiPromiseBuilder(api);

  const promiseRace = Promise.race([
    apiPromise('eventOne'),
    apiPromise('eventTwo'),
    apiPromise('eventThree')
  ]);

  api.load();

  return promiseRace;
;

或者使用async/await:

async function waitForEvent(api) 

  const apiPromise = apiPromiseBuilder(api);

  const promiseRace = Promise.race([
    apiPromise('eventOne'),
    apiPromise('eventTwo'),
    apiPromise('eventThree')
  ]);

  api.load();

  const firstResult = await promiseRace;

  return firstResult;
;

【讨论】:

那是我的直觉,也是我害怕的。以为我会在***上问一下。我对 async/await 持观望态度,如果在某些情况下必须将它与 Promise 混合使用,我不确定一直使用 Promise 并暂时放弃 async/await 是否更好。感谢您的详尽回答。 async/await 是基于 promise 的,只是隐藏了一些东西。你总是使用 Promise,尽管不是每次都明确表示。话虽如此,每种情况都是独一无二的,做你喜欢做的更好:) 似乎它不仅在幕后隐藏了东西,而且还施加了限制,例如仅返回一个变量,并且......好吧..我的帖子所涉及的整个限制。感谢您的反馈!

以上是关于我可以使用 async/await 来等待 JavaScript 中的多个事件吗?的主要内容,如果未能解决你的问题,请参考以下文章

async/await 函数不等待。多个功能不按顺序运行和完成

异步等待正确使用

等待 async/await 结果返回,以便使用这些值呈现动态 html

用 async/await 来处理异步

JavaScript async/await 没有正确等待?

Node.js 使用 async/await 读取文件