Есть ли у Promise время, в конце концов, оно "отклонит" себя, если оно никогда не будет разрешено в течение определенного периода времени?

Это приходит мне в голову, потому что я написал небольшой тег сценария для загрузки сценария через обещание получения сценария от стороннего сервиса. Я думал, что если сторонняя служба будет постоянно загружаться, не отказываясь от результата, то что произойдет с этим обещанием? Есть ли способ обойти такую ​​крайнюю ситуацию? является ли добавление тайм-аута для всего loadScript самым разумным способом сделать это?

function loaderScript(scriptUrl){
        return new Promise(function (res, rej) {
            let script = document.createElement('script');
            script.src = scriptUrl;
            script.type = 'text/javascript';
            script.onError = rej;
            script.async = true;
            script.onload = res;
            script.addEventListener('error',rej, { once: true });
            script.addEventListener('load',res, { once: true });
            document.head.appendChild(script);
        })
    }


loaderScript('https://...com').then(() => {...}).catch(() => { ... })

1 ответ

У 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 события, которые инициируются. Тайм-ауты браузера иногда могут быть длинными и не стандартными (они могут отличаться от одного браузера к другому), поэтому часто полезно добавить свой собственный тайм-аут, которым вы управляете.

Некоторые другие комментарии к вашему коду:

  1. Вам не нужно делать оба .onError и слушать за error событие. Выберите один или другой.
  2. Вам не нужно использовать once:true, Во-первых, события load и error не будут вызваны более одного раза. Во-вторых, даже если они это сделали, это не причиняет вреда, потому что обещания разрешаются или отклоняются только один раз. Как только вы решили или отклонили его, они защелкиваются и вызывают res() или же rej() не буду ничего делать после этого.
  3. Всегда безопаснее установить .src свойство last после того, как все обработчики событий присоединены, поэтому нет никаких шансов пропустить какие-либо события.
  4. Лучше отклонить с указанием причины, чтобы вызывающий абонент мог проверить, что могло произойти.
Другие вопросы по тегам