本文首发个人博客 - blog.cdswyda.com,转载务必保留做者和出处,以便追溯和错误修正。php
本文关键点: window.onload
和 页面上 ajax
的成功回调到底哪一个先触发。html
答案是不肯定。ajax
以前遇到一个现象,在父页面弹出一个Dialog加载一个子页面,在onload回调中传递一个参数给子页面,子页面异步ajax成功回调中要使用这个变量。json
然而出现的状况是在ajax的成功回调中大多数状况下是取不到这个在onload传来的值,可是偶尔又是能够的。浏览器
查阅此Dialog源码,以上逻辑能够进行以下简化。异步
父页面:post
<iframe id="iframe" src="./iframe.html" onload="onLoad()" frameborder="0"></iframe> <script> function onLoad() { console.log('iframe load'); document.getElementsByTagName('iframe')[0].contentWindow.onLoad('load'); } </script>
子页面:测试
<script> $.ajax('./test.json').done(function (a) { console.log('ajax结果'); console.log(a); }); function onLoad(e) { console.log('window onload') console.log(e); }; </script>
因为iframe的 onload
即要加载页面的 window.onload
,所以状况能够进一步简化为一个页面中究竟是 window.onload
先触发仍是 ajax
的成功回调先触发。this
测试代码:url
<script> $.ajax('./test.json').done(function (a) { console.log('ajax结果'); console.log(a); }); function onLoad(e) { console.log('window onload') console.log(e); }; window.onload = onLoad; </script>
这个页面除了在测试的script以前引入了jQuery没有其余代码,应该毫无疑问,是 window.onload
先触发,以后才是 ajax
的成功结果。
结果也证实是 window.onload
先触发,上面代码在浏览器运行结果为:
// window onload // Event {} // ajax结果 // {}
MDN上关于 window.onload
有以下解释:
The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links and sub-frames have finished loading.
那么问题就来了,若是必然是 window.onload 先触发,那么是不可能出现最开始的问题的。
继续修改测试代码,再加上一些东西:
<script> $.ajax('./test.json').done(function (a) { console.log('ajax结果'); console.log(a); }); function onLoad(e) { console.log('window onload') console.log(e); }; window.onload = onLoad; // 其余代码xxx // 模拟一个一分钟循环 var t1 = new Date().getTime(); while(new Date().getTime() - t1 < 1 * 60 * 1000) { document.querySelectorAll('*'); } </script>
写入一个一分钟的循环后,结果发生了改变:
// ajax结果 // {} // window onload // Event {}
这么来看就奇怪了呀, ajax
的成功比 window.onload
先触发。
关于这个现象,我也没找到权威的解释。
本身给了一个“合理”的解析:
window.onload
会在当前任务队列的最后一个触发。如最开始的例子,ajax
异步,还没有给出结果,页面须要等待的全部内容已经完成,任务队列为空,所以 window.onload
触发。
然后面这个因为 ajax
后面还有很长的代码要执行,这段代码推迟了 onload
的触发,同时这段代码还未执行完成时,以前异步的ajax已经返回告终果,成功回调的代码已经被加到了任务队列,所以 ajax
回调执行后才触发 window.onload
。
为了进一步验证我上面的想法,那么只要保证页面资源执行完成时,ajax尚未解决便可。
所以仍是上面的代码,可是将请求的内容换成一个真实接口,这个真实接口返回的数据更晚便可。
使用php暂停120s再返回结果,代码以下:
<?php sleep(120); echo '{"response":"two minutes later."}' ?>
结果倒是如上面估计的同样:
// window onload // Event {} // ajax结果 // {"response":"two minutes later."}
能够说明以前的“合理”解释确实是合理的。
因此异步的 ajax
和 window.onload
到底哪一个会先触发是不肯定,和你js代码(或者其余onload要等待的资源,如一个图片加载很慢等)以及这个 ajax
的解决时间有关系。
所以这种状况下的传值就不能以这种方式进行,能够换成更稳妥的方式,如直接跨页面操做或者放在url进行传递。