【问题标题】:Resolving a promise after some time t or if an event fires, whichever occurs first在某个时间 t 或事件触发后解决一个承诺,以先发生者为准
【发布时间】:2021-04-29 00:55:58
【问题描述】:

我有一个名为wait 的函数,它接受以毫秒为单位的时间并返回一个承诺。如果myEvent 被触发或在一段时间后ms 以先发生者为准,则承诺应该得到解决。目前我正在做这样的事情,我认为这不是正确的做法。

async function wait(ms) {
    return new Promise((res) => {
        myEmitter.on('myEvent', res);
        setTimeout(res, ms);
    });
}

有没有更好的方法来做到这一点?

【问题讨论】:

  • 调用者不想知道事件和超时之间的区别吗?
  • @jfriend00 我的用例不需要

标签: javascript node.js events eventemitter


【解决方案1】:

你正在做的很好。¹一旦承诺得到解决(通过第一次调用 resolve 函数或 reject 函数,使用它们的常用名称),调用 resolve/reject再次函数根本不做任何事情。因此,您所拥有的就是编写它的简单方法。

如果您在事件处理程序或超时处理程序中执行带有 res(doSomethingAndReturnValue()) 之类的副作用的操作,那么 将不是一个好主意,因为 doSomethingAndReturnValue() 部分仍会执行并具有副作用。但是在您的示例中,您没有这样做。


¹ 三个相当小的音符:

  1. 我假设当你的事件处理程序被调用时,一些信息被传递给处理程序。由于您将res 直接用作处理程序,因此它将接收该信息。因此,您已将其设置为使用事件处理程序获得的值(如果事件首先触发)或undefined(如果计时器首先触发)来履行承诺,这意味着使用它的代码会看到不同的履行值。

  2. 通常我希望超时是拒绝而不是履行,但这取决于您的用例。

  3. 您的函数不需要async 修饰符,因为它从不使用await。函数不需要 async 仅仅因为它返回一个承诺。大约一年前对规范进行了规范性更改,如果您在执行操作时从 async 函数返回本机承诺(它过去常常延迟事情非常短暂),但没有理由这样做。

【讨论】:

  • 我像这样发出事件,没有任何数据。 myEmitter.emit('myEvent') 我认为这使得等待函数总是返回未定义。关于异步部分,是的,我不知道为什么我把它放在那里:joy
  • @AdityaDS - 嘿,这就是我做出假设的结果。 ;-) 编码愉快!
【解决方案2】:

您的代码是正确的。一个 Promise 只能解决一次 - 如果您解决两次,第二次实际上是空操作。

话虽如此,作为替代方案,您可以使用具有相同想法的Promise.race。它以 Promise 作为输入,并会在 Promise 的第一个输入完成时产生一个 Promise。

例如,单击此处的按钮会完成一个承诺,但它也会在 10 秒内完成:

let buttonResolve;
let buttonPromise = new Promise(res => buttonResolve = res);

document.querySelector("button")
  .addEventListener("click", buttonResolve)

let timedPromise = new Promise(res => setTimeout(res, 10000));
let start = Date.now();
Promise.race([buttonPromise, timedPromise])
  .then(() => console.log(`finished in ${(Date.now() - start) / 1000}s`))
<button>Click me</button>

【讨论】:

  • 哇!不知道Promise.race 感谢您的回答!
  • @AdityaDS - 是的,race 是有用的 promise 组合器 之一。全套为allraceallSettledany。 ...
  • ...This post on the V8 blog 很好地概述了它们。
  • 哦,太好了!非常感谢分享!
猜你喜欢
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 2017-09-07
  • 2018-03-30
  • 2020-02-01
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
相关资源
最近更新 更多