在Google的API javascript示例中使用脚本异步/延迟/加载使用

时间:2018-01-09 17:13:32

标签: javascript google-api

在Google为其API提供的各种javascript示例中(例如here),他们使用以下代码从html加载脚本:

<script async defer src="https://apis.google.com/js/api.js" 
    onload="this.onload=function(){};handleClientLoad()" 
    onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

我的理解是async/defer告诉浏览器何时加载和执行脚本并且彼此有些矛盾。我几乎没有问题:

  1. 在此使用asyncdefer的含义是什么? 上下文?
  2. Google为何选择使用此技术?它有没有 表现或其他好处?
  3. onload事件中,为什么他们首先为事件分配一个空函数(function(){};) 在致电handleClientLoad()之前?
  4. 如果我想将整个javascript移动到单独的js文件中, 什么是加载这两个脚本的最佳方法?自从新的js文件 将取决于 api.js 并且无法异步加载?
  5. 感谢。

1 个答案:

答案 0 :(得分:2)

the WHAT-WG living standard for HTML's section on async and defer完全涵盖了这一点,其中包括这个方便的图形:

enter image description here

  

1。在这种情况下同时使用async和defer是什么意思?

如果浏览器支持async,则会忽略defer并执行异步操作。如果没有,但它支持defer,则会延迟。如果它也不支持,脚本会阻止DOM解析,但所有现代浏览器都支持至少一个。

  

2.为什么谷歌选择使用这种技术?它有任何表现或其他好处吗?

async在不阻止DOM解析和呈现的情况下获取脚本,并在可用时立即运行,即使DOM解析和呈现仍在进行中。 defer也将避免阻止DOM解析和呈现,但在解析完成之前不会运行脚本(例如,可能稍后)。

  

3。在onload事件中,为什么他们在调用function(){};之前首先为事件分配一个空函数(handleClientLoad()?)

如果你看onreadystatechanged,这一点就变得清晰了:基本上它确保handleClientLoad只被GAPI调用一次,而不是两次(一次由onload调整一次,一次调用onreadystatechanged }。)

  

4。如果我想将整个javascript移动到单独的js文件,那么加载这两个脚本的最佳方法是什么?由于新的js文件将依赖于api.js并且无法异步加载?

好吧,可以异步加载,你只需要用api.js来处理竞争条件。我可能会:

  1. handleClientLoad标记加载script之上的内联脚本中加api.js,如下所示:

    var clientLoaded = false;
    function handleClientLoad() {
        if (!clientLoaded &&
            typeof mainScriptLoad !== "undefined" &&
            typeof gapi !== "undefined") {
            clientLoaded = true;
            mainScriptLoad();
        }
    }
    
  2. 在单独的文件中添加mainScriptLoad

  3. 在单独文件的末尾,请致电handleClientLoad

  4. 那样:

    • 如果您的脚本先运行,它会调用handleClientLoad,但handleClientLoad会看到GAPI尚未加载且不会执行任何操作;之后,当加载GAPI时, 将调用handleClientLoad,这将调用mainScriptLoad,因为一切准备就绪。
    • 如果您的脚本在加载GAPI后运行,它将调用handleClientLoad,但handleClientLoad会看到您的主脚本尚未加载,而不是尝试调用它。稍后,当您的脚本加载并调用handleClientLoad时,handleClientLoad会调用mainScriptLoad,因为一切准备就绪。