【问题标题】:Resolve promise on external event解决外部事件的承诺
【发布时间】:2020-12-18 03:30:02
【问题描述】:
我想在不同函数中发生事件时解决一个承诺
const trigger = function() {}
const eventHandler = async function() {
while(true) {
await new Promise (resolve => {
}
// Code when the promise fulfills.
}
}
const cleaner = function() {
trigger()
}
cleaner()
【问题讨论】:
标签:
javascript
promise
callback
【解决方案1】:
您可以通过重新分配trigger 轻松做到这一点:
let trigger = () => {}
const eventHandler = async function() {
while(true) {
await new Promise (resolve => {
trigger = resolve
// ^^^^^^^^^^^^^^^^^
}
// Code when the promise fulfills.
}
}
const cleaner = function() {
trigger() // calls resolve to fulfill the currently waited-for promise
}
eventHandler() // start waiting
cleaner()
但是,请注意,这通常被认为是一种不好的做法,您应该启动任何导致外部事件的方法,尤其是安装事件侦听器,在new Promise 执行器回调中,您可以在其中可以轻松访问resolve 函数。
【解决方案2】:
下面是一个示例,说明如何使承诺可取消。我们使用了一个辅助函数 makeCancelable() ,它接受一个承诺,并返回一个不同的承诺和一个取消函数。没有办法只是“取消”现有的承诺,特别是当你无法控制承诺的做出方式时,但你可以做的是将现有的承诺包装在一个新的承诺中,它的行为就像原来的一样,但是也准备好根据命令解析。
// Helper function that just waits for a timeout
const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
function makeCancelable(promise) {
let resolveWrappedPromise
return {
promise: new Promise((resolve, reject) => {
resolveWrappedPromise = resolve
promise.then(resolve, reject)
}),
cancel: value => resolveWrappedPromise(value),
}
}
cancelPromise = () => {} // function used by onClick event
async function eventHandler() {
while (true) {
const { promise, cancel } = makeCancelable(wait(1000).then(() => 'Success!'))
cancelPromise = cancel
console.log(await promise)
}
}
eventHandler()
<button onclick="cancelPromise('Canceled!')">Cancel!</button>
在此代码示例中,“成功!”将每秒打印一次 - 除非您按下按钮取消当前的承诺。重复按下按钮将延迟“成功!”被打印的不确定,因为承诺被取消并提供了值“取消!”取消发生的时间。
【解决方案3】:
使用 EventEmitter2 包 (Live demo) 的 waitFor 方法。
import EventEmitter2 from "eventemitter2";
const emitter = new EventEmitter2();
(async () => {
const data = await emitter.waitFor("test");
console.log("emitted", data);
})();
setTimeout(() => emitter.emit("test", 1, 2, 3), 1000);