简体   繁体   English

使用Promise区分外部脚本标签onload事件和执行的外部脚本标签

[英]Using Promises to Distinguish between external Script Tag onload event and external Script Tag executed

When you have code like this: 当您有这样的代码时:

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);

it is not actually true that the external script has executed and therefore stuff is ready to do at the onload point. 外部脚本已执行并因此在onload点已经准备好了,这并不是真的。 Am I right in saying that onload does not mean "after the browser has processed and executed the JS and the external JS objects are ready to use"? 我的意思是说onload并不意味着“在浏览器处理并执行JS并且可以使用外部JS对象之后”?

If this is true, is there a way to check that the browser has executed the script? 如果是这样,是否有办法检查浏览器是否已执行脚本? I've tried using document.currentScript and that does not seem to deal with the execution delay. 我已经尝试过使用document.currentScript,但这似乎无法解决执行延迟。

Note that the jquery is just an example, I know that I can check for jquery using window.jQuery or typeof The situation I'm interested in is where you don't know what objects may be available after execution, where you're blind to the contents of the external script. 请注意,jquery只是一个例子,我知道我可以使用window.jQuerytypeof检查jquery。我感兴趣的情况是,您不知道执行后哪些对象可用,而您盲目外部脚本的内容。

One approach I have been looking into is using Promises. 我一直在研究的一种方法是使用Promises。 In the following code, I set up a promise (the content of which does not really matter) and then get the promise to report. 在下面的代码中,我设置了一个Promise(其内容并不重要),然后获得了Promise报告。

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);

With my limited understanding of the internals of Chrome JS execution, my understanding is that the following will happen in this order 由于对Chrome JS执行内部机制的了解有限,我的理解是以下将按此顺序进行

  1. Script Tag created 脚本标签已创建
  2. External Script Loaded 外部脚本已加载
  3. Promise created and control handed back to the browser 创建承诺并将控制权交还给浏览器
  4. Browser will then continue executing the downloaded external script 浏览器将继续执行下载的外部脚本
  5. Once that execution has finished, the promise will resolve 一旦执行完成,诺言就会解决

It would have the advantage of waiting for the external script to execute (which may itself call loads of other scripts). 这将具有等待外部脚本执行的优势(它本身可能会调用其他脚本的负载)。 Does that make any sense to anyone? 这对任何人有意义吗?

Any answers gratefully received. 感谢收到任何答案。

You can do the following: 您可以执行以下操作:

// 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);
    }
}

Last but not least, you will need to define after how many iterations an error message should be displayed to the user. 最后但并非最不重要的一点是,您将需要定义在几次迭代后应向用户显示一条错误消息。

EDIT: 编辑:

For any other script, you can check a given method "myFunction" was loaded or a given variable like this: 对于任何其他脚本,您可以检查是否已加载给定方法“ myFunction”或给定变量,如下所示:

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

}

if (myVariable) {

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM