JS分为同步任务和异步任务,好比:ajax
// 同步任务
console.log('start');
function first() {
console.log('first');
second();
}
function second() {
console.log('second');
}
first();
// 异步任务
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
})
process.nextTick(function() {
console.log('nextTick');
})
复制代码
同步任务都在主线程上执行,造成一个执行栈promise
以上同步任务的执行过程图解: 浏览器
主线程以外,事件触发线程管理着一个消息队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。
一旦执行栈中的全部同步任务执行完毕(此时JS引擎空闲),系统就会读取消息队列,将可运行的异步任务添加到可执行栈中,开始执行。bash
Promise.resolve().then(function() {
console.log('promise1');
})
console.log('end');
复制代码
then
;console.log('end')
;console.log('promise1')
;end, promise1
浏览器为了可以使得JS内部task与DOM任务可以有序的执行,会在一个task执行结束后,在下一个 task执行开始前,对页面进行从新渲染(task->渲染->task->...)
属于宏任务的有:setTimeout,setInterval等与timer有关的异步
微任务是一个任务队列,这个队列的执行顺序是在清空执行栈以后。
属于微任务的有Promise,process.nextTick,ajax等
process.nextTick的概念和then不太同样,process.nextTick是加入到执行栈底部,因此和其余的表现并不一致,属于执行栈的一部分
函数
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
resolve();
}).then(function() {
console.log('then');
})
console.log('console');
复制代码
setTimeout
,那么将其回调函数注册后分发到宏任务Event Queuenew Promise
当即执行console.log('promise');
then
函数分发到微任务的消息队列中console.log('console')
,当即执行then
函数拿到主线程执行console.log('then')
setTimeout
promise, console, then, setTimeout
到此就结束了。oop
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
复制代码