在承诺中使函数超时的最佳一般做法是什么

What is the best general practice to timeout a function in promise

本文关键字:是什么 最佳 承诺 函数 超时      更新时间:2023-09-26

使用超时来承诺函数调用

我已经看到许多资源提供了使用Promise.race在给定时间段内使函数调用超时的类似示例。这是在实践中如何使用Promise.race的一个很好的例子。下面是一些示例代码:

function doWithinInterval(func, timeout) {
    var promiseTimeout = new Promise(function (fulfill, reject) {
       // Rejects as soon as the timeout kicks in
       setTimeout(reject, timeout);
    });
    var promiseFunc = new Promise(function (fulfill, reject) {
        var result = func(); // Function that may take long to finish
        // Fulfills when the given function finishes
        fulfill(result);
    });
    return Promise.race([promiseTimeout, promiseFunc]);
}

上面使用 Promise.race 的简单方法会在超时启动后立即拒绝承诺func完成。否则,一旦func函数在超时间隔之前完成,项目就会完成。

这听起来不错且易于使用。

但是,这是在承诺中使用超时的最佳实践吗?

当然,如果我们想使用 Promise 对函数调用设置超时,则可以采用上述方法。这些行动似乎仍然是一个良好的承诺。但是,这是否被认为是在承诺中使用超时的好做法?如果没有,使用它有什么缺点?

我一直在寻找替代方法,但找不到本机 Promise 方法来做到这一点。

相反,一些外部 Promise 库提供timeout功能,如下所示:

  • 蓝鸟用品.timeout()

  • WinJS也提供.timeout()

  • Q 还附带.timeout() .

但是,Promise.timeout()似乎不是标准 ECMAScript 6 API 的一部分(如果我错了,请纠正我)。是否有任何推荐的方法可以使用 ES6 承诺在本地处理超时?

这取决于您所说的超时是什么意思。

如果希望函数停止,则不会。

如果你只是想停止等待它,那么是的(在 ES6 中快速鞭打):

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var timeout = (p, ms) => Promise.race([p, wait(ms).then(() => {
    throw new Error("Timeout after " + ms + " ms");
})]);

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var timeout = (p, ms) => Promise.race([p, wait(ms).then(() => {
  throw new Error("Timeout after " + ms + " ms");
})]);
// Example:
var log = msg => div.innerHTML += "<p>" + msg + "</p>";
var failed = e => log(e.toString() + ", line " + e.lineNumber);
log("Waiting 5 seconds...");
timeout(wait(5000), 2000)
.then(() => log("...Done."))
.catch(failed);
<div id="div"></div>

如果你想取消操作(让它停止),那么希望该操作附带一个 API 来取消它,你应该使用它,因为 ES6 承诺不是控制面。

可取消的承诺在 ES6 中是一个有争议的话题,但提到的一些库确实提供了这个概念。

本机 Promise.race 方法不会在实际承诺完成后清除超时承诺的计时器,因此该过程将等到超时承诺也完成。这意味着,如果您将超时设置为 1 小时并且我们的承诺在 1 分钟后完成,那么该过程将等待 59 分钟才能退出。

请改用此方法:

export function race({promise, timeout, error}) {
  let timer = null;
  return Promise.race([
    new Promise((resolve, reject) => {
      timer = setTimeout(reject, timeout, error);
      return timer;
    }),
    promise.then((value) => {
      clearTimeout(timer);
      return value;
    })
  ]);
}