js是单线程
javascript在最初设计时设计成了单线程,为什么不是多线程呢?如果多个线程同时操作DOM岂不会很混乱?比如,假定JavaScript同时有两个线程,一 个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?这里所谓的单线程指的是主线程是单线程的,所以在Node 中主线程依旧是单线程的。
浏览器的event-loop
执行栈与任务队列
(1)所有同步任务都在主线程上执行,形成一个执行栈。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置
一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步
任务,于是结束等待状态,进入执行栈
,开始执行。
(4)主线程不断重复上面的第三步。
复制代码
任务队列分为macro-task(宏任务)和micro-task(微任务)。
macro-task(宏任务): setTimeout, setInterval, setImmediate, I/O等
micro-task(微任务): process.nextTick, 原生Promise(有些实现的promise将then方法放到了宏任务中),Object.observe(已废弃), MutationObserver等
console.log(1);
console.log(2);
Promise.resolve().then(function(){
console.log('promise')
});
setTimeout(function(){
console.log('setTimeout1')
Promise.resolve().then(function(){
console.log('promise')
});
})
setTimeout(function(){
console.log('setTimeout2');
});
复制代码
结果:
1
2
promise
setTimeout1
promise
setTimeout2
浏览器 会先执行同步代码 ===> 然后查看任务队列 ===> 先执行micro-task(微任务) ===> 在执行macro-task(宏任务)
个人理解: 有微先走微,没微就走宏。复制代码
Nodejs的event-loop
Nodejs与浏览器的 event-loop有些不同
nodeJS中的宏任务和微任务在浏览器的基础上有新增了几个
微任务
then
nextTick
messageChannel
mutationObersve
宏任务
setTimeout
setInterval
setImmediate
nodejs的event-loop图解
当node执行完同步代码时就会执行上图的顺序
console.log(1);
console.log(2);
Promise.resolve().then(function(){
console.log('promise')
});
setTimeout(function(){
console.log('setTimeout1')
Promise.resolve().then(function(){
console.log('promise')
});
})
setTimeout(function(){
console.log('setTimeout2');
});
复制代码
node环境里的执行顺序
1
2
promise
setTimeout1
setTimeout2
promise
node 执行完同步代码 之后会先查找 微任务队列 然后逐一清空 微任务 然后走timer 清空timer(宏任务)复制代码
node里的的 nextTick 与 setImmediate
process.nextTick(function(){ console.log('nextTick')});setImmediate(function(){ console.log('immediate')});
nextTickimmediate因为 nextTick是微任务 所以nextTick先执行复制代码