-
Notifications
You must be signed in to change notification settings - Fork 0
/
async.html
137 lines (116 loc) · 5.28 KB
/
async.html
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>async</title>
</head>
<body>
<script>
// ES2017 标准引入了 async 函数,使得异步操作变得更加方便
// 是 Generator 函数的语法糖
// async函数对 Generator 函数的改进
// (1)内置执行器
// async函数的执行,与普通函数一模一样
// (2)更好的语义
// (3)更广的适用性
// async函数的await命令后面,可以是Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)
// (4)返回值是 Promise
// async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖
// async函数返回一个 Promise 对象,可以使用then方法添加回调函数
// 当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('Hello World', 1000);
/*// 使用形式
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};*/
// async函数返回一个 Promise 对象
// async函数内部return语句返回的值,会成为then方法回调函数的参数
async function f() {
return 'Hello Alvin';
}
f().then(data => console.log(data));
// async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态
// 抛出的错误对象会被catch方法回调函数接收到
async function foo() {
throw new Error('出错了');
}
foo().then(data => console.log(data)).catch(err => console.log(err));
// async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完
// 才会发生状态改变,除非遇到return语句或者抛出错误
// 正常情况下,await命令后面是一个 Promise 对象
// 如果不是,会被转成一个立即resolve的 Promise 对象
// await命令后面的 Promise 对象如果变为reject状态,
// 则reject的参数会被catch方法的回调函数接收到
// 即使前一个异步操作失败,也不要中断后面的异步操作
// 一种方法是将前一个await放在try...catch结构里面
async function bar() {
try {
await Promise.reject('出错了');
} catch(err) {
}
return await Promise.resolve('Hello Kathy');
}
bar().then(v => console.log(v));
// 另一种方法是await后面的 Promise 对象再跟一个catch方法,处理前面可能出现的错误
async function foobar() {
await Promise.reject('出错了').catch(err => console.log(err));
return await Promise.resolve('love you, Kathy');
}
foobar().then(v => console.log(v));
// 注意事项:
// 1. await命令后面的Promise对象,运行结果可能是rejected
// 所以最好把await命令放在try...catch代码块中或者在后面增加catch方法
// 2. 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发
/*// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;*/
// 3. await命令只能用在async函数之中,如果用在普通函数,就会报错
// async 函数的实现原理
/*async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () {
// ...
});
}*/
// spawn函数就是自动执行器
// 异步处理方法比较
// Promise 的写法比回调函数的写法大大改进,但是一眼看上去
// 代码完全都是 Promise 的 API(then、catch等等),操作本身的语义反而不容易看出来
// Generator 函数语义比 Promise 写法更清晰,但是必须有一个任务运行器
// Async函数的最简洁,最符合语义,几乎没有语义不相关的代码,也不需要自己提供执行器
// 异步遍历器(还在提案阶段)
</script>
</body>
</html>