Являются ли JavaScript вечно ожидающие обещания плохими?
Скажи, у меня есть обещание под названием myProm
и сказать, что у меня есть обработчики успеха и ошибок под названием onSuccess
а также onError
,
Всякий раз, когда мое обещание занимает больше 10 секунд, я хочу функцию timeoutHandler
быть выполненным, но если это произойдет, ни onSuccess
ни onError
должен быть выполнен. (Точно так же, если либо onSuccess
или же onError
работает, я не хочу, чтобы мой timeoutHandler
быть выполненным.)
Я придумал следующий фрагмент для этого.
new Promise((suc, err) => {
let outOfTime = false;
const timeoutId = window.setTimeout(() => {
outOfTime = true;
timeoutHandler();
}, 10000);
myProm.then(
(...args) => {
if (!outOfTime) {
window.clearTimeout(timeoutId);
suc(...args);
}
},
(...args) => {
if (!outOfTime) {
window.clearTimeout(timeoutId);
err(...args);
}
}
);
}).then(onSuccess, onError);
Однако в случае тайм-аута мое новое определенное обещание будет всегда. Может ли это иметь негативные побочные эффекты? Например, среда выполнения не может очистить объект Promise, потому что он все еще ожидает (или что-то в этом роде).
2 ответа
Там не должно быть никаких побочных эффектов. Это была бы ошибка браузера, если бы не ссылаться Promise
в каком бы состоянии ни находились ресурсы.
Просто убедитесь, что вы не держите ссылки на Promise
возражать, и все будет в порядке.
Помните, что некоторые API, такие как setTimeout
сохранит ссылку на закрытие до значения тайм-аута. Это означает, что если у вас большой тайм-аут, например, 10 с, вы должны очистить его, как только он вам больше не нужен. В противном случае ваш код может вызвать тысячи setTimeout
в течение 10 секунд, и каждый из них будет хранить ссылку на закрытие, которое в вашем случае будет ссылаться на Promise
,
Ты можешь использовать Promise.race()
, задавать timeoutHandler
как функция, которая возвращает отклоненный Promise
через десять секунд, иначе onSuccess
должен быть вызван при исполнении Promise
из myProm
function myProm() {
return new Promise((success, err) => {
setTimeout(() => {
success("myProm")
}, Math.floor(Math.random() * 11000))
})
}
function timeoutHandler() {
return new Promise((_, timeout) => {
setTimeout(() => {
timeout(new Error("timeoutHandler"));
}, 10000)
})
}
function onSuccess(data) {
console.log("success", data)
}
function onError(err) {
console.log("err:", err)
}
function onTimeout(e) {
if (e.message && e.message === "timeoutHandler") {
console.log(e.message + " handled");
}
else {
onError(e)
}
}
Promise.race([myProm(), timeoutHandler()])
.then(onSuccess, onTimeout);