在 promise 中使函数超时的最佳一般做法是什么
What is the best general practice to timeout a function in promise
承诺超时函数调用
我看到许多资源提供了使用 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 中使用超时的最佳实践吗?
当然,如果我们想为使用 Promises 的函数调用设置超时,则可以采用上述方法。这些操作似乎仍然是一个很好的承诺。但是,这是否被认为是在 Promise 中使用超时的良好做法?如果不是,使用它的缺点是什么?
我一直在寻找替代方法,但找不到原生的 Promise 方法。
相反,一些外部 Promise 库提供 timeout
功能,如下所示:
蓝鸟用品.timeout()
WinJS 也提供 .timeout()
Q 还带有 .timeout()
.
但是,Promise.timeout()
似乎不是标准 ECMAScript 6 API 的一部分(如果我错了,请纠正我)。有没有推荐的方法来使用 ES6 Promises 本地处理超时?
这取决于你所说的超时是什么意思。
如果您希望函数停止,则不会。
如果你只是想停止等待它,那么可以(在 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 承诺不是控制面。
Cancelable promises 在 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;
})
]);
}
承诺超时函数调用
我看到许多资源提供了使用 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 中使用超时的最佳实践吗?
当然,如果我们想为使用 Promises 的函数调用设置超时,则可以采用上述方法。这些操作似乎仍然是一个很好的承诺。但是,这是否被认为是在 Promise 中使用超时的良好做法?如果不是,使用它的缺点是什么?
我一直在寻找替代方法,但找不到原生的 Promise 方法。
相反,一些外部 Promise 库提供 timeout
功能,如下所示:
蓝鸟用品
.timeout()
WinJS 也提供
.timeout()
Q 还带有
.timeout()
.
但是,Promise.timeout()
似乎不是标准 ECMAScript 6 API 的一部分(如果我错了,请纠正我)。有没有推荐的方法来使用 ES6 Promises 本地处理超时?
这取决于你所说的超时是什么意思。
如果您希望函数停止,则不会。
如果你只是想停止等待它,那么可以(在 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 承诺不是控制面。
Cancelable promises 在 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;
})
]);
}