setTimeout(function(){
alert("I'm in setTimeout");
},0);
alert("I'm not in setTimeout");
问题三:下面的两段代码,分别的执行情况是怎样的呢?
setTimeout(function(){alert("setTimeout1);while(true){};},1000);
setTimeout(function(){alert("setTimeout2);},2000);
setTimeout(function(){alert("setTimeout3);},3000);
alert("over");
var flag = true;
setTimeout(function(){ flag = false; }, 1000);
while(flag){ }
alert("end");
假如你都能很快地回答出上面的问题,那恭喜你,你对javascript的单线程执行处理应该是有一定的了解的了。如果还不能很快地回答出来,那么相信你看了下面的解析后,也能很好地回答了。
看了上面的问题陈述后,你是否能得到上面问题的答案了呢?让我们来看一下。
问题一:javascript引擎执行是单线程的,可以实现异步是由于与浏览器内核中的线程相互配合完成的,由浏览器去完成一些如定时器的计数,当达到需要时间需要执行时,把任务插入到javascript引擎的线程中排队等待被执行,这里有个问题,假如当前有其它的任务执行时间较长,那么上述插入的任务会补延后,因此setTimeout函数的第二个时间参数time,实际会是等于或大于time执行,即假如是10s,有可能刚好10s执行,有可能是11s执行,不可能是9s执行。
java或c#这些语言中,是真正的支持多线程的,与javascript有本质的不同。
问题二:执行顺序会是"I'm not in setTimeout",再到"I'm in setTimeout",为什么?setTimeout中第二个参数是0,为什么不是马上执行?上面的问题陈述说了,定时器是由浏览器去计数的。javascript引擎的线程在执行这段代码时,setTimeout函数首先被调用,然后扔给浏览器的线程去定时计算,不得结果的返回,javascript引擎的线程马上执行下一段代码,即alert("I'm not in setTimeout");当浏览器的线程计算是0,需要执行时,把里面需要执行的代码插入到javascript引擎的线程中进行排队,然后javascript引擎的线程就会执行这个任务,输出"I'm in setTimeout"。
因此,使用了setTimeout(function(){},0)与直接执行的区别是,setTimeout会扔到浏览器中,再插入到javascript引擎线程中,然直接执行就是javascrtip引擎线程直接执行了。关于应用场景,这里有个比较直观的例子。
问题三:第一段代码,输出是"over",再到"setTimeout1",最后javascript引擎不会再响应和执行其它任务,因为javascript引擎是单线程的,到执行alert("setTimeout1")后,一直在执行while(true){};
第二段代码同样的道理,setTimeout会被先放到浏览器去计数,然后执行while(flag){};之后javascript引擎一直在执行这段代码,即使后面的浏览器计算到期把任务插入到队列中,也不会被javascript引擎执行,因为它是单线程,因此flag就不会被设置为false,所以"end"也不会被输出,这段代码的执行结果就是浏览器像”卡死了“,不会有任何输出。
1、javascript引擎只有一个线程,异步事件是由于有浏览器的配合得以完成,浏览器往javascript引擎的线程队列插入任务,与java中的多线程有本质区别;
2、如果一个计时器被阻塞执行,例如当前执行的其它任务耗时>定时的时间,它被执行的时间点会比预期更长。
本人是初学者,上面的描述可能有不够严谨或者是错误的地方,请大家批评指出。