Javascript 承诺本身有时间吗?如果承诺在特定的时间段内从未得到解决,它最终会“拒绝”自己吗?

Javascript 承诺本身有时间吗?如果承诺在特定的时间段内从未得到解决,它最终会“拒绝”自己吗?,javascript,asynchronous,promise,xmlhttprequest,script-tag,Javascript,Asynchronous,Promise,Xmlhttprequest,Script Tag,我之所以想到这一点,是因为我写了一个小脚本标签,通过承诺从第三方服务获取脚本来加载脚本。我在想,如果第三方服务将在不放弃备份结果的情况下持续加载,那么该承诺会发生什么?有没有解决这种边缘案件的办法?向整个loadScript添加超时是最聪明的方法吗 function loaderScript(scriptUrl){ return new Promise(function (res, rej) { let script = document.createEl

我之所以想到这一点,是因为我写了一个小脚本标签,通过承诺从第三方服务获取脚本来加载脚本。我在想,如果第三方服务将在不放弃备份结果的情况下持续加载,那么该承诺会发生什么?有没有解决这种边缘案件的办法?向整个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(() => { ... })
承诺本身有时间吗?如果承诺在特定时间内从未得到解决,它最终会拒绝承诺本身吗

承诺没有内置的超时。如果没有什么可以解决或拒绝它们,它们将永远处于“待定”状态

如果需要,您可以构建自己的超时

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);
    })
}
但是,浏览器在发出请求时确实有超时,因此插入脚本标记最终会触发
加载
错误
事件。浏览器超时有时可能很长,而且不是标准超时(不同浏览器的超时可能不同),因此添加自己控制的超时通常很有用

关于代码的其他一些注释:

  • 您不需要同时执行
    .onError
    和侦听
    错误事件。挑一个或另一个
  • 您不需要使用
    一次:true
    。首先,加载和错误事件不会被调用多次。第二,即使他们这样做了,在这里也没有什么坏处,因为承诺只能解决或拒绝一次。一旦您解决或拒绝了它,它们将被锁定,然后调用
    res()
    rej()
    将不会执行任何操作
  • 在附加所有事件处理程序之后,将
    .src
    属性设置为最后一个总是最安全的,这样就不会错过任何事件
  • 最好是有理由地拒绝,这样调用者就可以检查可能发生的情况

  • 如果您愿意,您可以添加一个超时。“持续加载而不放弃备份结果”是什么意思?@jfriend00 iow,api速度很慢,它试图从api检索数据,但从未得到响应,同时也从未长时间失败。