JS事件处理程序能否中断另一个处理程序的执行?

3
我有以下问题。我创建了一个类,在其构造函数中加载了一些图像,我需要延迟剩余的初始化操作直到它们完全加载完成。我使用的代码如下(摘自构造函数):

```

var self = this;
var imagesToLoad = 4;

var finishInit = function() {
    alert(imagesToLoad);
    imagesToLoad--;
    if (imagesToLoad == 0) {
       // remaining initializations
    }
}

this._prevIcon = new Image();
this._prevIcon.onload = finishInit; 
this._prevIcon.src = "img1.png";
this._nextIcon = new Image();
this._nextIcon.onload = finishInit; 
this._nextIcon.src = "img2.png";
this._pauseIcon = new Image();
this._pauseIcon.onload = finishInit; 
this._pauseIcon.src = "img3.png";
this._playIcon = new Image();
this._playIcon.onload = finishInit; 
this._playIcon.src = "img4.png";

令我惊讶的是,当在Firefox 7中执行时,显示的对话框为4,4,4,4;而在IE 9中,则是4,3,2,4。我很困惑,因为我认为JS是单线程的,因此一个事件处理程序不应该打断另一个。这是什么原因(或我的错误)呢?
提前致谢。 最好的问候, Tomek

尝试在“src”和“onload”之间切换这些行。 - CamelCamelCamel
1个回答

7
所有的JS事件处理程序都是单线程的。一个事件不会开始,直到前一个事件完成。它通过事件队列来工作。当一个事件完成时,JS引擎会查看队列中是否有另一个事件,如果有,则开始执行该事件。
例如,当计时器触发指示计时器事件的时间到达时,它将该事件放入队列中。当当前执行的JS事件完成并且计时器事件到达队列顶部时,计时器事件的代码就会执行。
有关JavaScript事件队列的进一步讨论,请参见this post
图像使用本机操作系统网络在后台加载。多个图像可以同时加载。.onload()处理程序一次只会触发一个,但是由于图像同时加载,因此无法保证代码中的加载顺序。此外,警报框可以影响时间,因为它们阻止了JavaScript的执行,但不会阻止图像加载的执行。
我也不理解4,4,4,4或4,3,2,4序列。它们都应该显示为4,3,2,1。要知道是什么原因导致这种情况,您需要向我们展示完全可工作的代码版本。我猜测您的变量作用域存在问题,或者您在问题中没有透露更多信息。
您可以在此处查看此类代码的工作版本:http://jsfiddle.net/jfriend00/Bq4g3/

1
关于警报功能可能有一些奇怪的问题。即使在警报旁边使用console.log,它也会正确地输出4、3、2、1。此外,我注意到即使警报读取4、4、4、4...,== 0条件也能得到正确解决。 - tomdz
感谢您详细而简洁的回答。 - Asad Hasan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接