8

我正在加载一个使用回调函数的外部脚本,它返回一些特定的数据。如果未收到此数据,则应显示错误。

这是我制作的代码:

<script>
//setting initial state so that function will only work once
var visitors_loaded=false;  
var my_callback = function( data ) {
    if (visitors_loaded) return 0;
    if (data) { 
        //success: callback function is called and it has a proper data
    visitors_loaded=true;
    alert(JSON.stringify(data));
    }
    else alert ('error'); //something went wrong
};
</script>
<script onload="my_callback(null)" onerror="my_callback(null)"
src="https://api.clicky.com/api/stats/4?site_id=32020&sitekey=9a19b1a4d1171193&type=visitors&date=this-month&output=json&json_callback=my_callback"></script>

如您所见...脚本可能会出错的许多事情,所以我自然地添加了一个onerror事件。如果您将脚本的主机名或域更改为不存在的内容,则此错误事件实际上会触发。

但是,如果您只更改脚本的 url,它仍然可以连接到服务器并触发onload事件。我的回调函数不会被那些无效请求调用,所以我也添加了一个onload处理程序。

现在的问题是,如果所有加载正常并返回数据,它将触发回调函数onload。我注意到在onload之前触发了回调函数并设置了visitor_loaded变量,以便只调用一次处理函数。

到目前为止,它在 JS fiddle 和我的离线站点中运行良好,但我想知道这是否是预期的行为?json_callback函数是否总是优先于onload处理程序?

https://jsfiddle.net/5sfk9ht5/4/

4

3 回答 3

3

旧 IE 中的 onload 可能不适用于Internet Explorer 中“脚本”标签的“onload”处理程序,如果您想运行所有浏览器,您可能需要类似https://jsfiddle.net/e287523t/2/的东西并且应该可以工作对所有人

      function addScript(fileSrc, callback) {
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.onreadystatechange = function() {
          if (this.readyState == 'complete') {
            callback();
          }
        } 
        script.onload = callback;
        script.src = fileSrc;
        head.appendChild(script);
     }

然后剩下的就是定义 my_callback 并调用 addScript

        my_callback = function(someData) {
          alert(JSON.stringify(someData));
        };
于 2016-06-15T02:28:54.367 回答
3

json_callback 函数是否总是优先于 onload 处理程序?

my_callback如果外部脚本同步调用,那么是的。

scripting官方html5 规范中的部分描述了这些东西应该如何工作。该规范非常笼统,必须处理很多关于编码、CORS 等的细节ignore-destructive-writes counter。但是对于这个问题,我们并不关心这些细节。

在第 4 步中有一条注释:

注意:这是脚本编译和实际执行的地方。

并在第 7 步load触发事件:

在脚本元素上触发一个名为 load 的简单事件。

所以规范定义load事件总是在脚本执行后触发。


如您所见,规范还告诉我们为什么onerror更改 URL 时不会触发事件。error仅当加载脚本失败时才会创建该事件。但所有请求都https://api.clicky.com/api/stats/ 返回 HTTP 200 状态。无效的 URL 会返回 XML,因此会引发 SyntaxError。但这不会导致onerror处理程序被触发。


正如其他人所提到的,如果异步调用回调,他们可以在onload事件发生后调用您的回调。但是我看不出他们为什么会在您的外部脚本中异步执行此操作的原因。

于 2016-06-20T13:16:19.147 回答
2

现在的问题是,如果所有加载正常并返回数据,它将触发回调函数和 onload。我注意到在 onload 之前触发了回调函数并设置了 visitor_loaded 变量,以便只调用一次处理函数。

这是因为回调是从 api.clicky.com 调用的脚本中启动的

到目前为止,它在 JS fiddle 和我的离线站点中运行良好,但我想知道这是否是预期的行为?

我明白你在说什么,关于脚本失败时会发生什么的相关问题在这里,但我为你做了一些测试,结果如下。

tester.html:

<script>

var onLoadTest = function() {
    console.log("Onload Called!");
};


var callbacktest = function() {
    console.log("Called from other script!");
};

var errortest = function() {
    console.log("Callback OnError!");
};

</script>

 <script onload="onLoadTest()" onerror="errortest()"
 src="script.js"></script>

脚本.js:

function otherScriptFunc()
{    
    //call the function in the original script
    callbacktest()
}

otherScriptFunc(); // first call to other script
setTimeout(otherScriptFunc, 0); // final call to other script

控制台日志的结果

Called from other script!
Onload Called!
Called from other script!
  1. 当其他地方的 JS 完成解析时,您OnLoad将被调用(异步函数将做自己的事情)。例如,otherScriptFunc();将在之前调用onloadsetTimeout(otherScriptFunc, 0);将在之后调用onload

  2. OnError只有在出现 GET 请求错误时才会调用您。IE,找不到文件,或无法解析 URL - 与文件中的内容无关。(我单独测试过,只是把文件名弄乱了)

  3. 只要其他脚本喜欢,就可以调用传递给其他脚本的回调。它有一个对它的引用,并且可以决定暂时保留它,然后在它玩完之后再调用它。这意味着它可能在异步调用中等待其他地方的数据。这意味着,理论上,您的 onload 实际上可以在回调之前调用,但这取决于其他脚本,您对此无能为力。

json_callback 函数是否总是优先于 onload 处理程序?

这与优先级无关,它仅取决于其他脚本何时决定调用它。

于 2016-06-15T02:12:27.073 回答