宏任务和微任务

一个很好的练习事件循环的网站 https://www.jsv9000.app/

JS 将 异步任务 分为宏任务和微任务

1. 同步代码(js 执行栈/回调栈)

2. 微任务的异步代码(js 引擎)

  • Process.nextTick(node)
  • Promise.then() catch()

    Promise 本身同步,then 和 catch 的回调函数是异步的微任务

  • Async/Await
  • Object.observe 等等

3. 宏任务的异步代码(宿主环境-浏览器、Node)

  • script(代码块)
  • Ajax/Fetch
  • setTimeout/setInterval
  • setImmediate

同步代码->微任务->宏任务

例子

例子 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
console.log(1);
setTimeout(function () {
console.log(2); //macro
}, 0);

const p = new Promise((resolve, reject) => {
console.log(3);
resolve(1000);
console.log(4);
});

p.then((data) => {
console.log(data); //micro
});

console.log(5);

打印结果:1 3 4 5 1000 2

例子 2

1
2
3
4
5
6
7
8
9
10
11
12
new Promise((resolve, reject) => {
resolve(1);
new Promise((resolve, reject) => {
resolve(2);
}).then((data) => {
console.log(data);
});
}).then((data) => {
console.log(data);
});

console.log(3);

打印结果: 3 2 1

例子 3

1
2
3
4
5
6
7
8
9
10
11
12
console.log(11);
setTimeout(() => {
console.log(12);
let p = new Promise((resolve) => {
resolve(13);
});
p.then((res) => {
console.log(res);
});
console.log(15);
}, 0);
console.log(14);

打印结果: 11 14 12 15 13

例子 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
setTimeout(() => {
console.log(1);
}, 0);

new Promise((resolve) => {
console.log(2);
resolve("p1");
new Promise((resolve) => {
console.log(3);
setTimeout(() => {
resolve("setTimeout2");
console.log(4);
}, 0);
resolve("p2");
}).then((data) => {
console.log(data);
});
setTimeout(() => {
resolve("setTimeout1");
console.log(5);
}, 0);
}).then((data) => {
console.log(data);
});
console.log(6);

打印结果:2 3 6 p2 p1 1 4 5

例子 5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log("script start");

setTimeout(() => {
console.log("setTimeout");
}, 0);
async1();

await async2();后面的代码的代码属于微任务

打印结果: script start 、 async1 start 、 async2 、async1 end 、setTimeout