栈和队列
- 栈(Stack):是一种后进先出的数据结构,进出口在同一个端口;
function a(){
console.log('a')
function b(){
console.log('b');
function c(){
console.log('c');
}
c();
}
b();
}
a();
// => a b c
// 函数调用顺序是a b c, 而作用域销毁的过程依次是c b a
- 堆(Queue):又叫队列,是一种先进先出的数据结构,进出口在不同的端口。
// 队列(堆)执行时按照放置的顺序依次执行
// 先进先出
setTimeout(function(){
console.log(1)
});
setTimeout(function(){
console.log(2)
});
setTimeout(function(){
console.log(3)
});
// => 1 2 3
浏览器事件环
-
宏任务和微任务
macrotask:
setTimeout
,setInterval
,事件
,script,ajax
,MessageChannel
,
setImmediate(IE)
,MessageChannel
,I/O
,requestAnimationFrame
microtask:
promise.then()
、MutationObserver
- 执行顺序
// 宏 异步1
setTimeout(() => {
console.log('setTimeout1');
// 微 异步
Promise.resolve().then(data => {
console.log('then3');
});
},1000);
// 微 异步2
Promise.resolve().then(data => {
console.log('then1');
});
// 微 异步3
Promise.resolve().then(data => {
console.log('then2');
// 宏 异步4
setTimeout(() => {
console.log('setTimeout2');
},1000);
});
// 同步
console.log(2);
// 2 then1 then2 setTimeout1 then3 setTimeout2
- 先执行栈中的内容,也就是同步代码,所以2被输出出来;
- 然后清空微任务,所以依次输出的是 then1 then2;
- 因代码是从上到下执行的,所以1s后 setTimeout1 被执行输出;
- 接着再次清空微任务,then3被输出;
- 最后执行输出setTimeout2
// 宏 异步
setTimeout(() => {
console.log(2);
// 微 异步
Promise.resolve().then(() => {
console.log(6);
});
}, 0);
// 微 异步
Promise.resolve(3).then((data) => {
console.log(data);
return data + 1;
// 微 异步
}).then((data) => {
console.log(data)
// 宏 异步
setTimeout(() => {
console.log(data + 1)
return data + 1;
}, 1000)
// 微 异步
}).then((data) => {
console.log(data);
});
// 3 4 undefined 2 6 5
// 宏 异步
setTimeout(() => {
console.log(1);
// 微 异步
Promise.resolve().then(data => {
console.log(2);
});
}, 0);
// 微 异步
Promise.resolve().then(data => {
console.log(3);
// 宏 异步
setTimeout(() => {
console.log(4)
}, 0);
});
// 同步
console.log('start');
// start 3 1 2 4
// 宏 异步
setTimeout(function () {
console.log(1);
// 微 异步
Promise.resolve().then(function () {
console.log(2);
});
});
// 宏 异步
setTimeout(function () {
console.log(3);
});
// 微 异步
Promise.resolve().then(function () {
console.log(4);
});
// 同步
console.log(5);
//5 4 1 2 3
// 宏 异步
setTimeout(() => {
console.log('A');
}, 0);
var obj = {
func: function () {
// 宏 异步
setTimeout(function () {
console.log('B')
}, 0);
// 同步
return new Promise(function (resolve) {
console.log('C');
resolve();
})
}
};
// 微 异步
obj.func().then(function () {
console.log('D')
});
// 同步
console.log('E');
// C E D A B
node事件环
- 宏任务和微任务
macrotask:
setTimeout
,setInterval
,setImmediate
,I/O
microtask:
promise.then
,process.nextTick
- 执行顺序
Node中是先执行主栈中的代码,执行完,先清空一轮微任务,再执行宏任务队列中的第1个,把宏任务执行了,再次去清空微任务
setTimeout(()=>{
console.log("timer1")
Promise.resolve().then(data=>{
console.log("then1")
})
})
Promise.resolve().then(data=>{
console.log("then2")
setTimeout(()=>{
console.log("timer2")
})
})
Promise.resolve().then(data=>{
console.log("then3")
})
// then2 then3 timer1 then1 timer2
setTimeout(()=>{
console.log("timer1")
Promise.resolve().then(data=>{
console.log("then3")
})
})
setTimeout(()=>{
console.log("timer2")
})
Promise.resolve().then(data=>{
console.log("then1")
})
Promise.resolve().then(data=>{
console.log("then2")
})
// then1 then2 timer1 then3 timer2
// then1 then2 timer2 timer1 then3
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')
})
})
// 1 7 6 8 2 4 9 3 11 10 5 12