File tree 8 files changed +115
-10
lines changed
8 files changed +115
-10
lines changed Original file line number Diff line number Diff line change
1
+ 异步的问题
2
+ ========
3
+
4
+ 故事必须从头说起,在很久很久以前……
5
+
6
+ ## 为校验表单,JavaScript 诞生了
7
+
8
+ 在那个拨号上网的洪荒年代,浏览器还非常初级,与服务器进行数据交互的唯一方式就是提交表单。用户填写完成之后,交给服务器处理,如果内容合规当然好,如果不合规就麻烦了,必须打回来重填。那会儿网速还是论 Kb 的,比如我刚上网那会儿开始升级到 33.6Kb,主流还是 22.4Kb……
9
+
10
+ 所以很容易想象:当用户填完100+选项,按下提交按钮,等待几十秒甚至几分钟之后,反馈回来的信息却是:“您的用户名不能包含大写”,他会有多么的崩溃多么的想杀人。为了提升用户体验,网景公司的[ 布兰登·艾克] ( https://zh.wikipedia.org/wiki/%E5%B8%83%E8%98%AD%E7%99%BB%C2%B7%E8%89%BE%E5%85%8B ) 大约用10天时间,开发出 JavaScript 的原型,从此,这门注定改变世界的语言就诞生了。
11
+
12
+ 只是当时大家都还不知道,发明它的目的,只是为校验表单。
13
+
14
+ ## JavaScript 中存在大量异步计算
15
+
16
+ 同样为了提升用户体验,HTML DOM 也选择了边加载,边生成,边渲染的策略。再加上要等待用户操作,大量交互都以事件来驱动。于是,JavaScript 就存在大量的异步计算。
17
+
18
+ 这也带来一个好处,作为一门 UI 语言,异步操作帮 JavaScript 避免了页面冻结。
19
+
20
+ 为什么异步操作可以避免界面冻结呢?
21
+
22
+ ### 同步的利弊
23
+
24
+ > 假设你去到一家饭店,自己找座坐下了,然后招呼服务员拿菜单来。
25
+
26
+ > 服务员说:“对不起,我是‘同步’服务员,我要服务完这张桌子才能招呼你。”
27
+
28
+ > 那一桌人明明已经吃上了,你只是想要菜单,这么小的一个动作,服务员却要你等待别人的一个大动作完成。你是不是很想抽ta?
29
+
30
+ 这就是“同步”的问题:顺序交付的工作1234,必须按照1234的顺序完成。
31
+
32
+ 不过它的也有好处:逻辑非常简单。你不用担心每步操作会消耗多少时间,反正每步操作都会在上一步完成之后才进行,只管往后写就是了。
33
+
34
+ ### 异步的利弊
35
+
36
+ 与之相反,异步,则是将耗时很长的 A 交付的工作交给系统之后,就去继续做 B 交付的工作。等到系统完成之后,再通过回调或者事件,继续做 A 剩下的工作。
37
+
38
+ 从观察者的角度,看起来 AB 工作的完成顺序,和交付他们的时间顺序无关,所以叫"异步"。
39
+
40
+ 所以,那些需要大量计算(比如 Service Worker),或者复杂查询(比如 Ajax)的工作,JS 引擎把它们交给系统之后,就回来继续待机了,于是我们总能看到浏览器第一时间响应我们的操作,感觉非常好。
41
+
42
+ 有利必有弊,异步的缺点就是:必须通过特殊的语法才能实现,而这些语法看起来就不如同步那样清晰明确了。
43
+
44
+ ## 异步计算的实现
File renamed without changes.
Original file line number Diff line number Diff line change @@ -67,9 +67,9 @@ new Promise( (resolve, reject) => {
67
67
});
68
68
```
69
69
70
- ## Await/ Async
70
+ ## Async Functions
71
71
72
- “微信 Web 开发者工具”里面集成了 Babel 转译工具,可以将 ES6 编译成 ES5,不过 Await/ Async 就不支持了。此时我们可以选择自行编译,或者只使用 Promise。
72
+ “微信 Web 开发者工具”里面集成了 Babel 转译工具,可以将 ES6 编译成 ES5,不过 Async Functions 就不支持了。此时我们可以选择自行编译,或者只使用 Promise。
73
73
74
74
自行编译时,请注意,小程序页面没有 ` <script> ` ,只能引用同名 ` .js ` ,所以要留神输出的文件名。这里建议把 JS 写在另一个文件夹,然后用 Babel 转译,把最终文件写过来。
75
75
Original file line number Diff line number Diff line change 1
1
其它场景
2
- ========
2
+ ========
3
+
4
+ 现在越来越多的库与框架都开始返回 Promise 对象,这里暂列一二。
5
+
6
+ ## Fetch API
7
+
8
+ Fetch API 是 XMLHttpRequest 的现代化替代方案,它更强大,也更友好。它直接返回一个 Promise 实例,并分两步返回结果。
9
+
10
+ 第一次返回的 ` response ` 包含了请求的状态,接下来可以调用 ` response.json() ` 生成新的 Promise 对象,它会在加载完成后返回结果。
11
+
12
+ ``` javascript
13
+ fetch (' some.json' )
14
+ .then ( response => {
15
+ if (response .ok ) {
16
+ return response .json ();
17
+ }
18
+ throw new Error (response .statusText );
19
+ })
20
+ .then ( json => {
21
+ // do something with the json
22
+ })
23
+ .catch ( err => {
24
+ console .log (err);
25
+ });
26
+ ```
27
+
28
+ 除了 ` response.json() ` 之外,它还有 ` .blob() ` ,` .text() ` 等方法,具体可以参考 [ MDN 上的文档] ( https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API ) 。
29
+
30
+ 它的浏览器覆盖率请看[ 这里] ( http://caniuse.com/#search=fetch ) ,值得注意的是,iOS 10.2 还不支持,所以现在必须提供兼容方案。
Original file line number Diff line number Diff line change 9
9
10
10
1 . 可读性更好
11
11
2 . 返回的结果可以加入任何 Promise 队列
12
- 3 . 可以使用 Await/ Async
12
+ 3 . 可以使用 Async Functions
13
13
14
14
我们就拿读取文件来举个例子。
15
15
@@ -86,7 +86,7 @@ doSomething()
86
86
// 继续处理
87
87
});
88
88
89
- // async/await
89
+ // async functions
90
90
await doSomething ();
91
91
if (await openConfirmPopup (' 确定么' )) {
92
92
// 继续处理
@@ -124,9 +124,9 @@ stat('.')
124
124
1 . 最后一个参数是回调函数
125
125
2 . 回调函数的参数为 ` (err, result) ` ,前面是可能的错误,后面是正常的结果
126
126
127
- ### 结合 Await/ Async 使用
127
+ ### 结合 Async Functions 使用
128
128
129
- 同样是上面的例子,如果想要结合 Await/ Async,可以这样使用:
129
+ 同样是上面的例子,如果想要结合 Async Functions ,可以这样使用:
130
130
131
131
``` javascript
132
132
const util = require (' util' );
Original file line number Diff line number Diff line change 1
1
回顾
2
2
========
3
3
4
+ ## Pormise
5
+
6
+ 相较于传统的回调模式,Promise 有着巨大的进步,值得我们学习和使用。
7
+
8
+ ### 优势
9
+
10
+ 1 . 可以很好地解决异步回调不好写、不好读的问题
11
+ 2 . 可以使用队列,并且在对象之间传递
12
+ 3 . 不引入新语言元素,大部分浏览器已经原生支持,可以放心使用;个别不支持的,也有完善的解决方案
13
+
14
+ ### 不足
15
+
16
+ 1 . 引入了不少新概念、新写法,学习成本不低
17
+ 2 . 也会有嵌套,可能看起来还很复杂
18
+ 3 . 没有真正解决 ` return/try/catch ` 的问题
19
+
20
+ ## Async Functions
21
+
22
+ 异步函数是 ES2017 里非常有价值的新特性,可以极大的改善异步开发的环境。
23
+
24
+ 除了覆盖率,几乎找不出什么黑点。
25
+
26
+ 目前大部分主流浏览器都已经实现对它的支持,除了 IE 和 iOS 10.2。我们可以针对这两个系列的浏览器里进行降级,不过请注意,因为 Async Functions 引入了新的语法元素,所以必须用 Babel 编译的方式来处理。
27
+
28
+ ## 一些小 Tips
29
+
30
+ 这是我犯过的一些错误,希望成为大家前车之鉴。
31
+
32
+ * ` .resolve() ` ` .reject() ` 不会自动 ` return ` 。
33
+ * Promise 里必须 ` .resolve() ` ` .reject() ` ` throw err ` 才会改变状态,` .then() ` 不需要。
34
+ * ` .resolve() ` 只会返回一个值,返回多个值请用数组或对象。
35
+
4
36
## 参考阅读
5
37
6
38
* [ 让微信小程序支持 ES6 的 Promise 特性] ( https://haojen.github.io/2016/11/23/wechat-app-promise/ )
Original file line number Diff line number Diff line change 21
21
22
22
* ES6 = ES2015
23
23
* ES7 = ES2016 + ES2017
24
+ * 异步函数 = Async Functions = Await/Async
24
25
25
26
范例代码中会使用 ES6 的一些语法,也会混用 ES6 Modules/CommonJS,请大家不要见怪。
26
27
Original file line number Diff line number Diff line change 1
1
# Summary
2
2
3
- * [ 前言] ( 00- README.md)
3
+ * [ 前言] ( README.md )
4
4
* [ 异步的问题] ( 01-issues-of-async.md )
5
5
* [ Promise 方案] ( 02-promise-intro.md )
6
6
* [ Promise 入门] ( 02-1-promise-basic.md )
7
7
* [ Promise 进阶] ( 02-2-promise-advanced.md )
8
- * [ Await/ Async 方案] ( 03-await-async.md )
9
- * [ Await/ Async 和 Promise 队列的异同 ] ( 03-1-difference-between-await-async-and-promise.md )
8
+ * [ Async Functions 方案] ( 03-await-async.md )
9
+ * [ Async Functions 和 Promise 的异同 ] ( 03-1-difference-between-await-async-and-promise.md )
10
10
* [ 一起实战吧] ( 04-lets-do-it.md )
11
11
* [ 降级] ( 04-1-downgrade.md )
12
12
* [ 小程序] ( 04-2-xiaochengxu.md )
You can’t perform that action at this time.
0 commit comments