Обещание - разрешение после нескольких событий - PullRequest
0 голосов
/ 29 августа 2018

Я использую обещание асинхронного подключения к API. API генерирует два события: connected и socketConnected.

Что касается моей функции connect(), я бы хотел дождаться, чтобы оба этих события сработали.

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

Однако вы можете разрешить только один раз, и я хочу, чтобы оба события сработали до разрешения обещания. Как я могу настроить это так, чтобы он вел себя таким образом?

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Я фанат кода многократного использования - если вы хотите тайм-аут для 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.all, которые получают одно обещание, которое разрешается, когда оба обещания разрешаются

т.е.

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

Хотя другой ответ лучше в этом случае, я предлагаю его только в том случае, если вы действительно хотите установить ограничение по времени для разрешения обещания

0 голосов
/ 29 августа 2018

Вам нужно использовать Promise.all для создания двух обещаний, по одному для каждого события, и когда оба разрешения - когда разрешается Promise.all - вы можете разрешить обещание, которое connect возвращает:

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();
    });
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...