它是保证一个标记,加载事件始终点火立即执行该脚本?

问题描述 投票:6回答:2

假设有两个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. 然后,用户代理必须开火脚本元素加载事件。

是否保证“其他脚本标记从未中断步骤1和2之间的过程”?

(编辑)在换句话说,我想知道有关HTML规范是否需要浏览器运行第一步第二步直通同步(标题为“马上”是指本)。

javascript html dom
2个回答
1
投票

每规格至少(实现从来没有保证的)是的,这保证了负载事件触发的"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);

0
投票

load事件将永远不会立即解雇,这是因为:

当资源及其相关资源完成加载负荷事件。

在一个内衬自调用函数是最接近的一个可以得到“立即”:

(function(){console.log("self-invoked");})();
© www.soinside.com 2019 - 2024. All rights reserved.