在一段时间 t 后或事件触发时解决承诺,以先发生者为准
Resolving a promise after some time t or if an event fires, whichever occurs first
我有一个名为 wait
的函数,它接受以毫秒为单位的时间和 returns 一个承诺。如果 myEvent
被解雇或一段时间后 ms
以先发生者为准,承诺应该得到解决。目前我正在做这样的事情,我认为这不是正确的做法。
async function wait(ms) {
return new Promise((res) => {
myEmitter.on('myEvent', res);
setTimeout(res, ms);
});
}
有更好的方法吗?
你做的很好。¹一旦承诺被确定(通过第一次调用 resolve
函数或 reject
函数,使用它们的常用名称),调用 resolve
/reject
函数再次不执行任何操作。所以你有的是简单的写法。
如果你在事件处理程序或超时处理程序中做一些有副作用的事情,比如 res(doSomethingAndReturnValue())
,that 不是一个好主意,因为 doSomethingAndReturnValue()
部分仍然执行并有其副作用。但在您的示例中,您没有这样做。
¹ 三个相当小的音符:
我假设当你的事件处理程序被调用时,一些信息被传递给处理程序。由于您直接使用 res
作为处理程序,它会收到该信息。因此,您将其设置为使用事件处理程序获得的值(如果事件首先触发)或使用 undefined
(如果计时器首先触发)来实现承诺,这意味着使用它的代码会看到不同的实现值.
通常我希望超时是拒绝而不是满足,但这取决于您的用例。
您的函数不需要 async
修饰符,因为它从不使用 await
。函数不需要 async
只是因为它 return 是一个承诺。从大约一年前对规范的规范性更改开始,如果您 return 来自 async
函数的本机承诺,它不再有任何区别(它过去常常延迟事情 非常),但没有理由。
您的代码是正确的。一个 promise 只能被解析一次——如果你解析它两次,第二次实际上是一个空操作。
话虽如此,您可以使用具有相同想法的 Promise.race
作为替代方案。它以承诺作为输入,并会产生一个承诺,该承诺会在承诺的第一个输入结算时结算。
例如,点击此处的按钮结算一个承诺,但它也会在 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>
我有一个名为 wait
的函数,它接受以毫秒为单位的时间和 returns 一个承诺。如果 myEvent
被解雇或一段时间后 ms
以先发生者为准,承诺应该得到解决。目前我正在做这样的事情,我认为这不是正确的做法。
async function wait(ms) {
return new Promise((res) => {
myEmitter.on('myEvent', res);
setTimeout(res, ms);
});
}
有更好的方法吗?
你做的很好。¹一旦承诺被确定(通过第一次调用 resolve
函数或 reject
函数,使用它们的常用名称),调用 resolve
/reject
函数再次不执行任何操作。所以你有的是简单的写法。
如果你在事件处理程序或超时处理程序中做一些有副作用的事情,比如 res(doSomethingAndReturnValue())
,that 不是一个好主意,因为 doSomethingAndReturnValue()
部分仍然执行并有其副作用。但在您的示例中,您没有这样做。
¹ 三个相当小的音符:
我假设当你的事件处理程序被调用时,一些信息被传递给处理程序。由于您直接使用
res
作为处理程序,它会收到该信息。因此,您将其设置为使用事件处理程序获得的值(如果事件首先触发)或使用undefined
(如果计时器首先触发)来实现承诺,这意味着使用它的代码会看到不同的实现值.通常我希望超时是拒绝而不是满足,但这取决于您的用例。
您的函数不需要
async
修饰符,因为它从不使用await
。函数不需要async
只是因为它 return 是一个承诺。从大约一年前对规范的规范性更改开始,如果您 return 来自async
函数的本机承诺,它不再有任何区别(它过去常常延迟事情 非常),但没有理由。
您的代码是正确的。一个 promise 只能被解析一次——如果你解析它两次,第二次实际上是一个空操作。
话虽如此,您可以使用具有相同想法的 Promise.race
作为替代方案。它以承诺作为输入,并会产生一个承诺,该承诺会在承诺的第一个输入结算时结算。
例如,点击此处的按钮结算一个承诺,但它也会在 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>