Какая лучшая общая практика для тайм-аута функции в обещании
Продвигайте вызов функции с тайм-аутами
Я видел, что многие ресурсы предоставляют похожие примеры использования 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 предлагают timeout
функциональность следующим образом:
Однако Promise.timeout()
не является частью стандартного API ECMAScript 6 (пожалуйста, поправьте меня, если я ошибаюсь). Есть ли какой-либо рекомендуемый способ обработки тайм-аутов изначально с ES6 Promises?
Ответы
Ответ 1
Это зависит от того, что вы подразумеваете под таймаутом.
Если вы ожидаете, что функция остановится, то нет.
Если вы просто хотите прекратить его ждать, тогда да (быстро взломать 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>
Ответ 2
Собственный метод 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;
})
]);
}