Есть ли у Promise время, в конце концов, оно «отклонит» себя, если оно никогда не будет разрешено в течение определенного периода времени? - PullRequest
0 голосов
/ 02 ноября 2018

Мне приходит в голову, потому что я написал небольшой тег сценария для загрузки сценария через обещание получения сценария от стороннего сервиса. Я думал, что если сторонняя служба будет постоянно загружаться, не отказываясь от результата, то что произойдет с этим обещанием? Есть ли способ обойти такую ​​крайнюю ситуацию? добавляет ли тайм-аут ко всему 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 Ответ

0 голосов
/ 02 ноября 2018

Есть ли у 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 последним после того, как все обработчики событий присоединены, поэтому нет никакой вероятности, что какие-либо события могут быть пропущены.
  4. Лучше отклонить с указанием причины, чтобы вызывающий абонент мог проверить, что могло произойти.
...