首页 > 代码库 > JavaScript 是单线程的而且是异步的机制
JavaScript 是单线程的而且是异步的机制
浏览器中的js程序是单线程的,那异步调用是怎么实现的呢?计时器是靠谁实现的呢?单线程难道是一边执行程序一边计时吗?
好了 …………之前就有好多的疑问 ,现在按我的理解和大家说一说
一、JavaScript单线程
在浏览器中,执行JS程序只有一个线程,所以是单线程,所以执行顺序就是从上到下依次执行,同一段时间内只能有一段代码被执行。你可能会问,为什么不用多线程呢,这样不是更能充分利用CPU吗?
ps:只能说早期的页面非常简单,所以我认为设计者没有考虑多线程的问题 (本人猜想的哈,勿喷!!)。另外,JavaScript主要用来处理用户与界面的交互,以及操作DOM;可以设想一下,如果一个线程要求删除DOM,另一个线程要求修改呢,浏览器听谁的??这就增加了程序设计的复杂度,所以简单点好啊,你说是不是。
ps:虽然JavaScript是单线程的,可是浏览器内部不是单线程的啊,你的一些I/O操作、定时器和事件监听是由浏览器提供的其他线程完成的……
##如果想利用多线程处理一些耗时较长的任务,可以使用HTML5提供的Web Worker、
二、任务队列和事件循环
理解异步机制的两个要点:任务队列和事件循环
ps:
三、异步机制
有了上面两节做铺垫,理解异步机制就容易多了。拿ajax来说,当页面的单线程执行xhr.send()
之后,对于页面来说发送任务已经完成了。怎么发送,那是浏览器的事,和单线程无关;什么时候响应,这事说不准。为了及时地得到响应的内容,在单线程中注册相应的事件就好xhr.onreadystatechange = fn() {...}
。注册之后,浏览器会在内部的其他线程中自动地帮我们监听该事件。直到该事件被触发,浏览器会在任务队列中添加一个任务等待该单线程执行。
四、定时器
setTimeout的作用是在间隔一定的时间后,将回调函数插入任务队列中,等栈中的同步任务都执行完毕后,再执行。因为栈中的同步任务也会耗时,所以间隔的时间一般会大于等于指定的时间。
setTimeout(fn, 0)
的意思是,将回调函数fn立刻插入任务队列,等待执行,而不是立即执行。看一个例子:
五、总结
所谓的单线程并不孤单,它的背后有浏览器的其他线程为其服务,其异步也得靠其他线程来监听事件的响应,并将回调函数推入到任务队列等待执行。单线程所做的就是执行栈中的同步任务,执行完毕后,再从任务队列中取出一个事件(没有事件的话,就等待事件),然后开始执行栈中相关的同步任务,不断的这样循环。
JavaScript 是单线程的而且是异步的机制