假设有两个JavaScript文件。
one.js
window.a=1;
two.js
window.a=2;
而装载机:loader.html
<body></body>
<script>
const s1=document.createElement("script");
s1.src="one.js";
s1.addEventListener("load",()=>console.log("one.js",window.a));
const s2=document.createElement("script");
s2.src="two.js";
s2.addEventListener("load",()=>console.log("two.js",window.a));
document.body.appendChild(s1);
document.body.appendChild(s2);
</script>
它总是产生为[out-1]或[OUT-2]? (编辑:这意味着既不是“我想,它总是产生[OUT-1]的码”,也不是“我要总是产生[OUT-2]的码”两者[OUT-1]和[OUT-2]是可接受。)
[OUT-1](在运行的顺序S1-exec-> S1-的onload - > S2-EXEC - > S2-的onload它是确定。):
"one.js" 1
"two.js" 2
[OUT-2](S2-exec-> S2-的onload - > S1-EXEC - > S1-的onload它也是OK):
"two.js" 2
"one.js" 1
我所令人担心的是该浏览器是否可以以S1-EXEC的顺序运行 - > S2-EXEC - > S1-的onload - > S2-的onload和产生为[out-3]
[OUT-3](不正常):
"one.js" 2
"two.js" 2
我查了HTML5规范https://www.w3.org/TR/2008/WD-html5-20080610/tabular.html#script
蚂蚁这样说的:
如果负载是成功的
- 如果脚本元素的文件在其浏览器上下文的活动文档,用户代理必须执行该脚本:....
- 然后,用户代理必须开火脚本元素加载事件。
是否保证“其他脚本标记从未中断步骤1和2之间的过程”?
(编辑)在换句话说,我想知道有关HTML规范是否需要浏览器运行第一步第二步直通同步(标题为“马上”是指本)。
每规格至少(实现从来没有保证的)是的,这保证了负载事件触发的"execute the script block"算法结束,但是...我不知道这样能保证你的事件处理程序将得到之后调用。
所以,一定要能够面对[OUT-1]和[出2],但[出3]目前还不太清楚。
当你追加文档中的<script>元素也将被装载作为async
脚本。这意味着,脚本1和脚本2之间执行的顺序不能保证。
// scr1 will load an external script
const scr1 = document.createElement('script');
scr1.onload = e => console.log('1', window.$);
scr1.src = 'https://cdn.jsdelivr.net/gh/jquery/[email protected]/dist/jquery.js?' + Math.random();
// scr2 will load a dataURL script
const scr2 = document.createElement('script');
scr2.onload = e => console.log('2', window.$);
scr2.src = 'data:application/javascript,$="script 2"';
// even though scr1 is appended first
document.head.appendChild(scr1);
document.head.appendChild(scr2);
但同时他们要求在执行脚本块algortithm结束触发事件,我不得不承认,我并不清楚,如果它是可能的争用情况可能不会发生,而且这两个执行前的脚本块发生第一Load事件处理程序进行处理(因为它只能在下次事件循环被称为回)。
但我想我们可以认为这是很好的,因为这种情况发生的几率是如此之低。 此外,它似乎至少Firefox和Chrome都在同一个事件循环执行事件回调的触发事件的一个(小于1ms脚本执行和的onload回调之间间隔)。
// both will load a dataURL where the execution time will get stored (minimal time possible)
// in onload events we will log
// both the script's execution time and the event's handler time
const scr1 = document.createElement('script');
scr1.onload = e =>
console.log('1', window.$, performance.now());
scr1.src = 'data:application/javascript,$=performance.now()';
const scr2 = document.createElement('script');
scr2.onload = e =>
console.log('2', window.$, performance.now());
scr2.src = 'data:application/javascript,$=performance.now()';
document.head.appendChild(scr1);
document.head.appendChild(scr2);
该load事件将永远不会立即解雇,这是因为:
当资源及其相关资源完成加载负荷事件。
在一个内衬自调用函数是最接近的一个可以得到“立即”:
(function(){console.log("self-invoked");})();