解决外部事件的承诺

Resolve promise on external event

我想在不同函数中发生事件时解决承诺

const trigger = function() {}

const eventHandler = async function() {
  while(true) {
    await new Promise (resolve => {
      
    }
    // Code when the promise fulfills.
  }
}

const cleaner = function() {
  trigger()
}

cleaner()

下面是一个示例,说明您可以如何使承诺可取消。我们正在使用一个接受承诺的辅助函数 makeCancelable() ,以及 returns 一个不同的承诺和一个取消函数。没有办法只“取消”现有的承诺,尤其是当您无法控制承诺的方式时,但您可以做的是将现有的承诺包装在一个新的承诺中,该承诺的行为与原始承诺一样,但是也准备好根据命令解决。

// 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>

在此代码示例中,“成功!”将每秒打印一次——除非你按下按钮取消当前的承诺。重复按下按钮将延迟“成功!”不会被不确定地打印出来,因为 promise 被取消并提供了值“Canceled!”取消发生的时间。

使用 waitFor method of the EventEmitter2 package (Live demo).

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); 

您可以通过重新分配 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 函数。