Event Loop

Promise

概念

  • new Promise((resolve, reject) => {}) 里面的函数是同步(立刻)执行,then/catch/finally里面的函数是异步(进入微任务队列)执行

  • 微任务队列:Promise.then/catch/finallyMutationObserverprocess.nextTickObject.observe

  • 宏任务队列:setTimeoutsetIntervalsetImmediaterequestAnimationFrameI/OUI rendering

  • 微任务队列优先级高于宏任务队列。在每一次事件循环中,只要调用栈为空,就会先执行微任务队列中的任务,直到微任务队列为空,再执行宏任务队列中的任务

示例 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
console.log(1);

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

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

promise.then((res) => {
console.log(res);
});

// 1 3 4 2

示例 2

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
26
27
28
29
30
31
32
33
34
35
36
37
38
const p1 = () =>
new Promise((resolve, reject) => {
console.log(1);

let p2 = new Promise((resolve, reject) => {
console.log(2);

const timeOut1 = setTimeout(() => {
console.log(3);
resolve(4);
}, 0);

resolve(5);
});

resolve(6);

p2.then((arg) => {
console.log(arg);
});
});

const timeOut2 = setTimeout(() => {
console.log(8);
const p3 = new Promise((reject) => {
reject(9);
}).then((res) => {
console.log(res);
});
}, 0);

p1().then((arg) => {
console.log(arg);
});

console.log(10);

// 1 2 10 5 6 8 9 3

示例 3

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
26
27
const p1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 3000);
});

const p2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 2000);
});

const p3 = new Promise((resolve) => {
setTimeout(() => {
resolve(3);
}, 1000);
});

function execute() {
p1.then((data) => console.log(data));
p2.then((data) => console.log(data));
p3.then((data) => console.log(data));
}

execute();

// 3 2 1 间隔1秒输出

Async/Await

概念

  • async 函数是 GeneratorPromise 的语法糖

  • async 函数返回一个 Promise 对象,await 表达式会暂停 async 函数的执行,等待 Promise 的解决,然后恢复 async 函数的执行并返回解决值

  • 可以转换成 Promise 的写法,见示例。实际并不是这么执行的!!!

示例 1

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

async function async2() {
console.log('3');
}

async1();

console.log('4');

// 1 3 4 2
  • 等价于
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function async1() {
console.log('1');
return async2().then(() => {
console.log('2');
});
}

function async2() {
console.log('3');
return Promise.resolve('');
}

async1();

console.log('4');

// 1 3 4 2

示例 2

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
26
27
const p1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 3000);
});

const p2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 2000);
});

const p3 = new Promise((resolve) => {
setTimeout(() => {
resolve(3);
}, 1000);
});

async function execute() {
await p1.then((data) => console.log(data));
await p2.then((data) => console.log(data));
await p3.then((data) => console.log(data));
}

execute();

// 1 2 3 等待3秒后输出
  • 等价于
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
26
27
28
29
30
31
32
33
34
35
36
const p1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 3000);
});

const p2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 2000);
});

const p3 = new Promise((resolve) => {
setTimeout(() => {
resolve(3);
}, 1000);
});

function execute() {
return p1
.then((data) => {
console.log(data);
return p2;
})
.then((data) => {
console.log(data);
return p3;
})
.then((data) => {
console.log(data);
});
}

execute();

// 1 2 3 等待3秒后输出

示例 3

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
26
27
28
29
30
async function async1() {
console.log('1');
return '2';
}

async function async2() {
console.log('3');
return Promise.resolve('4');
}

async function test() {
console.log('5');
const v1 = await async1();
console.log(v1);
const v2 = await async2();
console.log(v2);
}

test();

var promise = new Promise((resolve) => {
console.log('6');
resolve('7');
});

promise.then((val) => console.log(val));

console.log('8');

// 5 1 6 8 2 3 7 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
26
27
28
29
30
31
32
33
34
function async1() {
console.log('1');
return Promise.resolve('2');
}

function async2() {
console.log('3');
return Promise.resolve('4');
}

function test() {
console.log('5');
return async1()
.then((v1) => {
console.log(v1);
return async2();
})
.then((v2) => {
console.log(v2);
});
}

test();

var promise = new Promise((resolve) => {
console.log('6');
resolve('7');
});

promise.then((val) => console.log(val));

console.log('8');

// 5 1 6 8 2 3 7 4

Promise 的 API 方法

Promise.all

  • Promise.all 方法接受一个 Promise 可迭代对象,并返回一个新的 Promise

  • 只有当所有的 Promiseresolve 时,返回的 Promise 才会 resolve,并以一个包含所有 resolve 值的数组作为结果

  • 如果任何一个 Promise reject,返回的 Promisereject,并带有该 Promisereject 原因

1
2
3
4
5
const p1 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'one'));
const p2 = new Promise((resolve, reject) => setTimeout(resolve, 200, 'two'));
const p3 = new Promise((resolve, reject) => setTimeout(resolve, 300, 'three'));

Promise.all([p1, p2, p3]).then(console.log); // ["one", "two", "three"]

Promise.race

  • Promise.race 方法接受一个 Promise 可迭代对象,并返回一个新的 Promise

  • 一旦迭代中的任何一个 Promise resolvereject,返回的 Promise 就会 resolvereject,并以该 Promiseresolve 值或 reject 原因作为结果

1
2
3
4
const p1 = new Promise((resolve, reject) => setTimeout(resolve, 500, 'one'));
const p2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'two'));

Promise.race([p1, p2]).then(console.log); // "two" (p2 resolves first)

Promise.any

  • Promise.any 方法接受一个 Promise 可迭代对象,并返回一个新的 Promise

  • 只要迭代中的任何一个 Promise resolve,返回的 Promise 就会 resolve,并以该 Promiseresolve 值作为结果

  • 如果所有的 Promisereject,返回的 Promisereject,并带有一个聚合的 reject 原因(一个 AggregateError 对象)

1
2
3
4
5
const p1 = new Promise((resolve, reject) => setTimeout(reject, 100, 'one'));
const p2 = new Promise((resolve, reject) => setTimeout(resolve, 200, 'two'));
const p3 = new Promise((resolve, reject) => setTimeout(resolve, 300, 'three'));

Promise.any([p1, p2, p3]).then(console.log); // "two" (p2 resolves first)