使用Promises来区分外部脚本标记onload事件和执行的外部脚本标记

时间:2017-04-21 18:13:48

标签: javascript

如果你有这样的代码:

var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.charset = 'utf-8';
scriptNode.onload = function() {
    console.log("Finished Loading Script");
   //do stuff here
}
scriptNode.async = false;
scriptNode.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js";
document.getElementsByTagName('body')[0].appendChild(scriptNode);

实际上外部脚本已经执行并且因此在onload点上已经准备好了。我是否正确地说onload并不意味着"在浏览器处理并执行了JS之后,外部JS对象就可以使用"?

如果是这样,有没有办法检查浏览器是否已执行脚本?我尝试过使用document.currentScript,但似乎没有处理执行延迟。

请注意,jquery只是一个示例,我知道我可以使用window.jQuerytypeof检查jquery我感兴趣的情况是你不知道的地方执行后可能有哪些对象,您对外部脚本的内容视而不见。

我一直在研究的一种方法是使用Promises。在下面的代码中,我设置了一个承诺(其内容并不重要),然后得到承诺报告。

function findScriptNode(source) {
    return new Promise(function(resolve) {
        var scripts = document.getElementsByTagName("script");
        for (var i=0;i<scripts.length;i++) {
            if (scripts[i].src && scripts[i].src === source) {
              var timestamp = Date.now();
              var finetimestamp = performance.now();
              console.log(source + " Promise Event Timestamp: " + timestamp + " Performance Timestamp: "  + finetimestamp);
              resolve();
              break;
            }
        }
    });
}

var source = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js";
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.charset = 'utf-8';
scriptNode.onload = function() {
      var timestamp = Date.now();
      var finetimestamp = performance.now();
      console.log(source + " Load Event Timestamp: " + timestamp + " Performance Timestamp: "  + finetimestamp);
      findScriptNode(source).then(success => { 
          timestamp = Date.now();
          finetimestamp = performance.now();
          console.log(source + " Promise Complete Event Timestamp: " + timestamp + " Performance Timestamp: "  + finetimestamp);
      });
}
scriptNode.async = false;
scriptNode.src = source
document.getElementsByTagName('body')[0].appendChild(scriptNode);

由于我对Chrome JS执行内部的理解有限,我的理解是以下将按此顺序发生

  1. 创建脚本标记
  2. 已加载外部脚本
  3. 创建承诺并将控制权交还给浏览器
  4. 浏览器将继续执行下载的外部脚本
  5. 执行完成后,承诺将解决
  6. 它具有等待外部脚本执行的优势(它本身可以调用其他脚本的负载)。这对任何人都有意义吗?

    感激地收到任何答案。

1 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

// initial call
setTimeout(function(){ checkJquery(); }, 3000);


function checkJquery() {
    if (window.jQuery) {  
        // jQuery is loaded  
        alert("Yeah!");
    } else {
        // jQuery is not loaded, check again in 3 seconds
        setTimeout(function(){ checkJquery(); }, 3000);
    }
}

最后但并非最不重要的是,您需要定义应向用户显示错误消息的迭代次数。

修改

对于任何其他脚本,您可以检查给定的方法&#34; myFunction&#34;加载或给定的变量如下:

if (typeof myFunction === "function") { 

}

if (myVariable) {

}