繁体   English   中英

承诺-解决多个事件后

[英]Promise - Resolving after multiple events

我使用诺言异步连接到API。 该API发出两个事件: connectedsocketConnected

根据我的connect()函数,我想等待这两个事件触发。

connect() {
  return new Promise((resolve,reject)=>{
    this._client.on('connected', resolve);
    this._client.on('socketConnected', resolve);
    setTimeout(reject, 5000);
  }
}

但是,您只能解决一次,而且我希望在诺言解决之前触发这两个事件。 如何设置它,使其表现出这种方式?

您需要使用Promise.all创建两个 promise,每个事件一个,并且当两个事件都解决时(当Promise.all解决时),您可以解析connect返回的promise:

connect() {
  return new Promise((resolveAll, rejectAll) => {
    Promise.all([
      new Promise(res1 => this._client.on('connected', res1)),
      new Promise(res2 => this._client.on('socketConnected', res2))
    ]).then(resolveAll);
    setTimeout(rejectAll, 5000);
  });
}

如果希望尽快进行垃圾收集,您还可以清除Promise.all解析时的超时:

connect() {
  return new Promise((resolveAll, rejectAll) => {
    const rejectTimeout = setTimeout(rejectAll, 5000);
    Promise.all([
      new Promise(res1 => this._client.on('connected', res1)),
      new Promise(res2 => this._client.on('socketConnected', res2))
    ]).then(() => {
      clearTimeout(rejectTimeout);
      resolveAll();
    });
  });
}

我喜欢可重用的代码-如果您发现自己想使Promise超时,那为什么不编写一个函数来这样做呢?

const promiseTimeout = (promise, timeout) => {
    let timer;
    return Promise.race([
        promise, 
        new Promise((_, reject) => (timer = setTimeout(reject, timeout, promiseTimeout.symbol)))
    ])
    .then(result => (clearTimeout(timer), result));
};
promiseTimeout.symbol = Symbol('timeout');

现在,您可以在需要设置承诺时限的任何地方使用它

在这种情况下,正如已经观察到的那样,您需要为您的逻辑提供两个 Promise,并将它们包装在Promise中。

const promise = Promise.all([
    new Promise(resolve => this._client.on('connected', resolve)),
    new Promise(resolve => this._client.on('socketConnected', resolve))
]);

现在,结合这两个代码段

const promiseTimeout = (promise, timeout) => {
    let timer;
    return Promise.race([
        promise, 
        new Promise((_, reject) => (timer = setTimeout(reject, timeout, promiseTimeout.symbol)))
    ])
    .then(result => (clearTimeout(timer), result));
};
promiseTimeout.symbol = Symbol('timeout');

function connect() {
    const promise = Promise.all([
        new Promise(resolve => this._client.on('connected', resolve)),
        new Promise(resolve => this._client.on('socketConnected', resolve))
    ]);
    return promiseTimeout(promise, 5000);
}

// if connect rejects with reason promiseTimeout.symbol, you can be sure it was because of the timeout

虽然,在这种情况下,其他答案更好,但我仅在您确实希望对承诺解决方案设置时间限制的情况下提供此答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM