javascript为何是单线程语言,缘由在于若是是多线程,当一个线程对DOM节点作添加内容操做的时候,另外一个线程要删除这个DOM节点,这个时候,浏览器应该怎么选择,这就形成了混乱,为了解决这类问题,在一开始的时候,javascript就采用单线程模式。javascript
在后面H5出的web worker标准的时候,看似是多线程,实际上是在一个主线程来控制其余线程,并且不能操做DOM,因此本质仍是单线程java
任务能够分为两种,一种为同步,另外一种为异步(具备回调函数)。以下图: node
主线程在任务队列中读取事件,这个过程是循环不断地,因此这种运行机制叫作Event Loop(事件循环)web
nextTick是在执行栈同步代码结束以后,下一次Event Loop(任务队列)执行以前。当全部同步任务执行完,会在queue中执行nextTick,不管nextTick有多少层回调,都会执行完毕后再去任务队列,因此会形成一直停留在当前执行栈,没法执行任务队列,请看下面代码浏览器
process.nextTick(function () {
console.log('nextTick1');
process.nextTick(function (){console.log('nextTick2')});
});
setTimeout(function timeout() {
console.log('setTimeout');
}, 0)
复制代码
执行完毕后输出nextTick一、nextTick二、setTimeout,缘由是nextTick是在当前执行栈末尾执行,而setTimeout是在下次任务队列在执行bash
setImmediate方法是在Event Loop(任务队列)末尾,也就是下一次Event Loop时执行。 setTimeout方法是按照执行时间,放入任务队列,有时快与setImmediate有时慢。请看如下代码多线程
setImmediate(function () {
console.log('setImmediate1');
setImmediate(function (){console.log('setImmediate2')});
});
setTimeout(function timeout() {
console.log('setTimeout');
}, 0);
复制代码
这段代码执行完多是setImmediate一、setTimeout、setImmediate2,也多是setTimeout、setImmediate一、setImmediate2,缘由是setTimeout和setImmediate1都是在下次Event Loop中触发,因此前后不肯定,可是setImmediate2确定是最后,由于他是在setImmediate1任务队列以后,也就是下下次Event Loop执行异步
Node.js也是单线程的Event Loop可是和浏览器有些区别,如图所示,socket
1.先经过Chrom V8引擎解析Javascript脚本函数
2.解析完毕后调用Node API
3.LIBUV库负责Node API的执行,将不一样任务分配给不一样的线程,造成一个Event Loop(任务队列)
4.最后Chrom V8引擎将结果返回给用户
node.js的特色是事件驱动,非阻塞单线程。当应用程序须要I/O操做的时候,线程并不会阻塞,而是把I/O操做交给底层库(LIBUV)。此时node线程会去处理其余任务,当底层库处理完I/O操做后,会将主动权交还给Node线程,因此Event Loop的用处是调度线程,例如:当底层库处理I/O操做后调度Node线程处理后续工做,因此虽然node是单线程,可是底层库处理操做依然是多线程
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
复制代码
上面处理阶段都是按照先进先出的规则执行回调函数,按顺序执行,直到队列为空或是该阶段执行的回调函数达到该阶段所容许一次执行回调函数的最大限制后,才会将操做权移交给下一阶段。
1.当setTimeout时间最小,读取文件不存在的时候
2.当setTimeout时间最小,读取文件存在的时候
3.当setTimeout时间为100毫秒,读取文件不存在的时候
4.当setTimeout时间为100毫秒,读取文件存在的时候
1.javascript和node.js都是单线程,可是node底层是多线程操做
2.Event Loop —— 任务队列
3.当同时设置nextTick, setImmediate, setTimeout时必定是nextTick先执行,nextTick不属于Event LOop,它属于v8的micro tasks,而且会阻塞Event Loop
4.setImmediate,setTimeout属于Event Loop可是,直接阶段不一样