javascript单线程 异步

来源:互联网 发布:sap 物料主数据 编辑:程序博客网 时间:2024/05/17 02:24

   单线程就是一脑筋地执行,上刀山下火海。但是异步就不是哦,它会停一停。那么两者好像互斥的赶脚。那么是不是javascript既支持单线程又支持异步呢?一开始看这些有关线程还有异步的东西,就觉得好遥远似的,不是我能够及的范围。但是借鉴了很多的文章,渐渐地对这个模糊的东西清晰了。

javascript单线程的解释

其实按照《javascript权威指南》中讲到,其实javascript核心语言没有包含任何线程机制的,还有客户端的javascript也是没有明确定义线程机制。但是javascript还是严格按照"单线程"的模型去执行代码。javascript的单线程就意味着脚本或者事件句柄在执行的时候是不能响应用户的输入的。javascript的单线程优点是简单,缺点是如果事件句柄执行的时间过长的话会出现浏览器假死。既然很多书都说javascript是单线程,那么为什么还有这个异步的概念呢?两者冲突吗?

javascript异步

出现我们感觉javascript这种语言是异步的原因如下:

(1)事件触发:为什么说事件触发机制会让我们觉得是异步呢?因为事件拥有回调函数,打破了原有的执行流程,所以这样子就会导致我们觉得是不是javascript另外开条线程给事件触发呢?我们先了解下事件触发的流程,但我们为一个DOM节点元素登记事件(如onclick),当那个元素触发了事件的时候,浏览器会在Document节点产生事件流,然后把该元素的事件触发函数(也叫回调函数)添加到队列的尾部中,而浏览器就负责排序和选择什么时间执行回调函数,所以不是另外开线程给事件触发。

(2)setTimeout 或者 setInterval函数:

function sleep(time) {var start = new Date().getTime();while (true) {if (new Date().getTime() - start > time) {break;}}}

那个代码应该不是很难去了解,就是使javascript代码在那个函数停留你所传的时间,然后再执行文档下面的代码。其实也就是相当于休眠那样子。

对于下面的函数,假如我们HTML代码中我们有img这个id的元素,然后我们来监听它的onclick事件

document.getElementById('img').onclick = function() {var d = new Date();//获取当前的时间console.log('start......' + d.getSeconds() + 'sec..' + d.getMilliseconds());//设置一个定时器,然后200毫秒后执行那个匿名函数。setTimeout(function() {var d1 = new Date();console.log('end......' + d1.getSeconds() + 'sec..'+ d1.getMilliseconds());}, 200);sleep(300); //最重要的是让点击事件函数执行300毫秒}

那么上面出现有两种情况,一种是如果javascript另外开一个线程给setTimeout函数的话,那么它会在200毫秒后执行匿名函数。一种是因为那个sleep函数影响所以导致它300毫秒后才执行那个匿名函数,那那,下图给你揭开谜底。


下面那个时间(setTimeout开始执行的时间)减去上面的时间(img被点击就开始计时),可以看出来就是大概300毫秒,不是200毫秒。那究竟为什么会出现上面的问题呢?javascript或者浏览器是怎么样实现的?让我一一道来。我们先看下面的一张流程图。

也就是说其实所谓的setTimeout是异步是因为定时器的代码在指定的时间(上面的例子是在205)被添加到队列,但是添加到队列中不代表是马上执行,而是尽快地执行,就是当javascript线程是空闲的时候,浏览器会被告知要去执行队列中的函数。所以在setTimeout的时间参数中,不是代表前一个函数参数是什么时候执行,而是什么时候把执行函数添加到队列中。执行不执行要看javascript线程是否空闲。从这个侧面也可以看出其实javascript是单线程的,所谓的异步只是一种假象。它总是把回调函数弄进队列中,然后在特定的时间执行该执行的函数。还有一点就是在计时的时候,也不是javascript引擎计时,而是交给浏览器去计时的

(3)ajax :对于ajax的话,在发送请求的时候,浏览器会开一条线程给它去发送请求。但是在onreadystatechange设置回调函数的话,也是一样那个回调函数会被放置到队列的尾部等待执行,还是基于上面的事件驱动模型。

最后感谢那些被我看的文章还有书籍,太多了,所以不能一一感谢,不过这里要感谢《javascript高级程序设计》这本书,讲得详细。