Есть ли у Promise время в конечном итоге reject
, если оно никогда не будет разрешено в течение определенного периода времени?
Обещания не имеют встроенного тайм-аута. Если ничто не разрешит или не отвергнет их, они навсегда останутся «ожидающими».
Вы можете создать свой собственный тайм-аут, если хотите.
function loaderScript(scriptUrl) {
return new Promise(function(res, rej) {
const TIMEOUT = 5 * 1000;
let timer = setTimeout(function() {
rej(new Error("Script load timeout"));
}, TIMEOUT);
let script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.addEventListener('error', function(e) {
rej(e);
clearTimeout(timer);
});
script.addEventListener('load', function() {
res();
clearTimeout(timer);
});
script.src = scriptUrl;
document.head.appendChild(script);
})
}
Но у браузеров есть тайм-аут на запросы, которые они делают, поэтому вставка тега скрипта должна в конечном итоге привести к срабатыванию событий load
или error
. Тайм-ауты браузера иногда могут быть длинными и не стандартными (они могут отличаться в разных браузерах), поэтому часто бывает полезно добавить свой собственный тайм-аут, которым вы управляете.
Некоторые другие комментарии к вашему коду:
- Вам не нужно одновременно выполнять
.onError
и прослушивать событие error
. Выберите одно или другое.
- Вам не нужно использовать
once:true
. Во-первых, события load и error не будут вызваны более одного раза. Во-вторых, даже если они это сделали, это не причиняет вреда, потому что обещания разрешаются или отклоняются только один раз. После того, как вы решили или отклонили его, они защелкиваются, и вызов res()
или rej()
ничего не сделает после этого.
- Всегда безопаснее устанавливать свойство
.src
последним после того, как все обработчики событий присоединены, поэтому нет никакой вероятности, что какие-либо события могут быть пропущены.
- Лучше отклонить с указанием причины, чтобы вызывающий абонент мог проверить, что могло произойти.