Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 98ccaaf

Browse files
committed
基本完成初稿,先提交了吧。
1 parent 3a18abf commit 98ccaaf

File tree

9 files changed

+1526
-40
lines changed

9 files changed

+1526
-40
lines changed

‎.gitignore‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44
node_modules
55

66
# test
7-
test
7+
test
8+
9+
# build
10+
build

‎03-1-async-function-vs-promise.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Async Function VS Promise
33

44
## 异步函数的优势
55

6-
异步函数对异步编程来说,是很大的进步。尤其在 `try/catch/throw` 方面,异步函数可以延续以前的标准写法,优势非常大。
6+
异步函数对异步编程来说,有非常很大的提升。尤其在 `try/catch/throw` 方面,异步函数可以延续以前的标准写法,优势非常大。
77

88
## Promise 的优势
99

@@ -13,7 +13,7 @@ Async Function VS Promise
1313

1414
异步函数返回的是一个 Promise 对象;`await` 关键字只能等待 Promise 对象完成操作。
1515

16-
所以关于 Promise 的知识都还有效,大家也必须学习 Promise,才能更好的使用异步函数。
16+
所以 Promise 的知识都还有效,大家也必须学习 Promise,才能更好的使用异步函数。
1717

1818
### Promise 能更好的提供队列操作,并且在对象之间传递
1919

‎03-async-function.md‎

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
Async Function
2+
========
3+
4+
Async Function,即异步函数,为异步编程带来了非常大的提升,瞬间把开发效率和维护效率提升了一个数量级。
5+
6+
它的用法非常简单,只要用 `async` 关键字声明一个函数为"异步函数",这个函数的内部就可以使用 await 关键字,让其中的语句等待异步执行的结果,然后再继续执行。我们还是用代码来说话吧:
7+
8+
```javascript
9+
function resolveAfter2Seconds(x) {
10+
return new Promise(resolve => {
11+
setTimeout(() => {
12+
resolve(x);
13+
}, 2000);
14+
});
15+
}
16+
17+
async function f1() {
18+
var x = await resolveAfter2Seconds(10);
19+
console.log(x);
20+
}
21+
f1();
22+
23+
// 输出:
24+
// (2秒后)10
25+
```
26+
27+
这段代码来自 [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)。里面先声明了 `resolveAfter2Seconds` 函数,执行它会返回一个 Promise 对象,等待2秒钟之后完成。然后声明了异步函数 `f1`,里面只有两行代码,第一行用 `await` 表示要等后面的 Promise 完成,再进行下一步;于是2秒之后,输出了"10"。
28+
29+
这段代码比较短,不太能体现异步函数的价值,我们改写一下查找最大文件的代码试试看:
30+
31+
```javascript
32+
const fs = require('./FileSystem');
33+
34+
async function findLargest(dir) {
35+
let files = await fs.readdir(dir);
36+
let stats = [];
37+
for (let i = 0, len = files.length; i < len; i++) {
38+
stats.push(await fs.stat(files[i]));
39+
}
40+
let file = stats
41+
.filter( stat => stat.isFile() )
42+
.reduce( (memo, stat) => {
43+
if (memo.size > stat.size) return memo;
44+
return stat;
45+
});
46+
return file;
47+
}
48+
49+
findLargest('path/to/dir')
50+
.then(file => {
51+
console.log(file);
52+
});
53+
```
54+
55+
怎么样,是不是异常清晰明了,连代码量都减少了很多。而且,因为每次 `await` 都会等待后面的异步函数完成,所以我们还无意间写出了生成队列的代码。当然你可能不希望要队列,毕竟都异步了,队列的吸引力实在不大,那么我们只需要把它改成下面这种样子就行了:
56+
57+
```javascript
58+
let stats = await Promise.all(files.map( file => fs.stat(file) ));
59+
```
60+
61+
酷不酷!想不想学?
62+
63+
## 设计
64+
65+
见识过异步函数的强大之后,我们来捋一捋一下它的具体设计。
66+
67+
异步函数主要由两部分组成:
68+
69+
### `async`
70+
71+
声明一个函数是异步函数。执行异步函数会返回一个 Promise 实例。异步函数的返回值会作为 `.then()` 的参数向后传递。
72+
73+
`async` 的语法比较简单,就在普通函数前面加个 `async` 而已。
74+
75+
### `await`
76+
77+
`await` 操作符只能用在异步函数的内部。表示等待一个 Promise 完成,然后返回其返回值。语法是这样的:
78+
79+
```javascript
80+
[return_value] = await expression;
81+
```
82+
83+
**return_value 返回值**:Promise 执行器的返回值
84+
**expression 表达式**:Promise 对象,其它类型会使用 `Promise.resolve()` 转换
85+
86+
使用 `await` 之后,异步函数会暂停执行,等待表达式里的 Promise 完成。`resolve` 之后,返回 Promise 执行器的返回值,然后继续执行。如果 Promise 被 `rejected`,就抛出异常。
87+
88+
## 捕获错误
89+
90+
异步函数最大的改进其实就在捕获错误这里。它可以直接使用 `try/catch/throw` 就想我们之前那样。
91+
92+
比如,一款前后端分离的应用,比如论坛块,需要用户登录,所以在初始化的时候就会去后端请求用户信息,如果返回了,就继续加载用户关注列表;如果 401,就让用户登录。用 Promise 的话,我们这样做:
93+
94+
```javascript
95+
function getMyProfile() {
96+
return fetch('api/me')
97+
.then(response => {
98+
if (response.ok) {
99+
return response.json();
100+
}
101+
})
102+
.then(profile => {
103+
global.profile = profile
104+
})
105+
.catch( err => {
106+
if (err.statusCode === 401) {
107+
location.href = '#/login';
108+
}
109+
})
110+
}
111+
```
112+
113+
这样做也不是不可以,但是如果业务逻辑越来越复杂,队列也会越来越长,也许每一步都需要处理错误,那么队列就会变得难以维护。
114+
115+
如果用异步函数就会简单很多:
116+
117+
```javascript
118+
async function getMyProfile() {
119+
let profile;
120+
try {
121+
profile = await fetch('api/me');
122+
global.profile = profile;
123+
} catch (e) {
124+
if (e.statusCode === 401) {
125+
location.href = '#/login';
126+
}
127+
}
128+
}
129+
```
130+
131+
另外,如果你真的捕获到错误,你会发现,它的堆栈信息是连续的,甚至可以回溯到调用异步函数的语句,继而可以审查所有堆栈里的变量。这对调试程序带来的帮助非常巨大。
132+
133+
## 普及率
134+
135+
[![Async Function 的普及率](http://images.gitbook.cn/000af860-5801-11e7-92d5-13bc6466d9ae)](http://caniuse.com/#search=async%20function)
136+
截图于:2017年06月23日

‎03-await-async.md‎

Lines changed: 0 additions & 36 deletions
This file was deleted.

‎10-review.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@
3535

3636
## 参考阅读
3737

38+
* [MDN Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
39+
* [MDN Promise 中文](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise)
40+
* [阮一峰:ECMAScript 6 入门 - Promise 对象](http://es6.ruanyifeng.com/#docs/promise)
41+
* [[翻译] We have a problem with promises](http://fex.baidu.com/blog/2015/07/we-have-a-problem-with-promises/)
42+
* [MDN Generator](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Generator)
43+
* [Async Function](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function)
44+
* [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)
3845
* [让微信小程序支持 ES6 的 Promise 特性](https://haojen.github.io/2016/11/23/wechat-app-promise/)
3946
* [util.promisify() in Node.js v8](http://farzicoder.com/util-promisify-in-Node-js-v8/)
4047
* [util.promisify 官方文档](https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original)

‎SUMMARY.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* [Promise 错误处理](02-2-promise-error.md)
1212
* [Promise 进阶](02-04-promise-advanced.md)
1313
* [Async Functions 方案](03-await-async.md)
14-
* [Async Functions VS Promise](03-1-difference-between-await-async-and-promise.md)
14+
* [Async Functions VS Promise](03-1-async-function-vs-promise.md)
1515
* [一起实战吧](04-lets-do-it.md)
1616
* [降级](04-1-downgrade.md)
1717
* [小程序](04-2-xiaochengxu.md)

‎gulpfile.js‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const fs = require('fs');
2+
const util = require('util');
3+
const gulp = require('gulp');
4+
const del = require('del');
5+
const sequence = require('run-sequence');
6+
const concat = require('gulp-concat');
7+
8+
const TO = 'build/';
9+
const readFile = util.promisify(fs.readFile);
10+
11+
gulp.task('clear', () => {
12+
del(TO);
13+
});
14+
15+
gulp.task('gitchat', async () => {
16+
let summary = await readFile('./SUMMARY.md');
17+
let chapters = /\]\(([^)]+\.md)\)/g[Symbol.match](summary)
18+
.map(chapter => chapter.slice(2, -1));
19+
return gulp.src(chapters)
20+
.pipe(concat('all.md', {
21+
newLine: '\n\r'
22+
}))
23+
.pipe(gulp.dest(TO + 'gitchat/'));
24+
});
25+
26+
gulp.task('default', callback => {
27+
sequence(
28+
'clear',
29+
'gitchat',
30+
callback
31+
);
32+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /