在这种情况下,如何避免嵌套承诺

时间:2020-03-24 15:57:17

标签: javascript promise async-await

如何使此代码段符合eslint规则,或者使我的代码更具可读性/雅致性而没有嵌套承诺?

class Sync {
  io = IO.getInstance();

  constructor(token) {
    this.token = token;
  }
  
  sendMessage = (
    data,
    retryTimeout = 0,
  ) => {
    const response = this.io.request(requestConfig); // should return a Promise
    const timeout = retryTimeout + 3000;
    // want to retry when AJAX error
    return response
      .catch(() => new Promise((resolve, reject) => {
        if (this.token === data.token) {
          // eslint warning: Avoid nesting promises.eslint(promise/no-nesting)
          setTimeout(() => this.sendMessage(data, timeout).then(resolve, reject), timeout);
        } else {
          reject(new Error('Failed to send message due to network offline'));
        }
      }));
  }
}

class Sync {
  async sendMessage(data, retryTimeout = 0) {
    const timeout = retryTimeout + 3000;
    try {
      await this.io.request(requestConfig); // should return a Promise
    } catch(e) {
      if (this.token === data.token) {
        await new Promise(resolve => {
          setTimeout(resolve, timeout);
        });
        return this.sendMessage(data, timeout);
      } else{
        throw new Error('Failed to send message due to network offline');
      }
    }
  }
我试图将其更改为async函数,现在可以吗?或我该如何正确设置?

谢谢。

1 个答案:

答案 0 :(得分:0)

使用.then(resolve, reject)Promise constructor antipattern。而是将其链接:

class Sync {
  sendMessage(data, retryTimeout = 0) {
    const response = this.io.request(requestConfig); // should return a Promise
    const timeout = retryTimeout + 3000;
    // want to retry when AJAX error
    return response.catch(() => {
      if (this.token === data.token) {
        return new Promise(resolve => {
          setTimeout(resolve, timeout);
        }).then(() => this.sendMessage(data, timeout));
      } else {
        throw new Error('Failed to send message due to network offline');
      }
    });
  }

如果将new Promise(…)setTimeout重构为delay辅助函数,那就更好了。