在JavaScript中重试承诺的一般解决方案



我尝试给出一个通用的解决方案。以下是我的方式,并且出现了"未被告求(承诺("的错误。

如何解决此问题?

function tryAtMost(maxRetries, promise) {
  let tries = maxRetries
    return new Promise(function(resolve, reject) {
        promise.then((result) => {
        resolve(result)
      })
        .catch(err => {
            if (tries > 0) {
                console.log(`tries with ${tries}`)
          tryAtMost(--tries, promise);
        } else {
          reject(err)
        }
        })
    })
}
tryAtMost(3, promise).then(result => {
  console.log(result)
})
.catch(err => {
  console.log(err)
})

您问的原因是您在catch中错过了resolve的电话:

.catch(err => {
    if (tries > 0) {
        console.log(`tries with ${tries}`);
        resolve(tryAtMost(--tries, promise)); // <=== ****
    }
    else {
        reject(err)
    }
})

...因此,您正在创造一个从未被任何事物所掌握的诺言,因此,如果它拒绝,您将获得无人驾驶的拒绝。


但是,tryAtMost有一个问题:它无法与您提供的信息一起使用,因为它不知道该尝试什么。您需要将其传递给执行者,而不是承诺,因为这是您需要重试的执行者的工作。这也使功能变得更加简单:

function tryAtMost(tries, executor) {
    --tries;
    return new Promise(executor)
        .catch(err => tries > 0 ? tryAtMost(tries, executor) : Promise.reject(err));
}

使用:

tryAtMost(4, (resolve, reject) => {
    // The thing to (re)try
});

示例:

function tryAtMost(tries, executor) {
  console.log(`trying, tries = ${tries}`);
  --tries;
  return new Promise(executor)
    .catch(err => tries > 0 ? tryAtMost(tries, executor) : Promise.reject(err));
}
tryAtMost(4, (resolve, reject) => {
  const val = Math.random();
  if (val < 0.3) {
    resolve(val);
  } else {
    reject(val);
  }
})
.then(result => console.log(result))
.catch(err => console.error(err));

最新更新