理解 async/await
2018-02-27 16:22
681 查看
http://blog.csdn.net/qq673318522/article/details/75331225
刚出来不久的 ES8 包含了
关键字
想较于 Generator,
* 内置执行器。Generator 函数的执行必须依靠执行器,而
* 更好的语义。
* 更广的适用性。
Thunk 函数或 Promise对象。而
Promise 或者 原始类型的值(Number,string,boolean,但这时等同于同步操作)
* 返回值是 Promise。
Iterator 对象方便,可以直接使用
先定义一个 Fetch 方法用于获取 github user 的信息:
2
3
4
5
6
7
8
9
10
Promise 方式
2
3
4
5
6
7
8
9
10
11
12
Promise 的方式虽然解决了 callback hell,但是这种方式充满了 Promise的
Generator 方式
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Generator 的方式解决了 Promise 的一些问题,流程更加直观、语义化。但是 Generator 的问题在于,函数的执行需要依靠执行器,每次都需要通过
async 方式
2
3
4
5
6
7
8
9
async 函数返回一个 Promise 对象
2
3
4
如果
2
3
4
5
async 函数返回的 Promise 对象,必须等到内部所有的 await 命令的 Promise 对象执行完,才会发生状态改变
也就是说,只有当
2
3
4
5
6
7
8
9
正常情况下,await 命令后面跟着的是 Promise ,如果不是的话,也会被转换成一个 立即 resolve 的 Promise
如下面这个例子:
2
3
4
如果返回的是 reject 的状态,则会被
先来看下面的例子:
2
3
4
5
6
如上面所示,当
reject 状态,则后面的
解决办法:可以添加
2
3
4
5
6
7
8
9
10
11
12
13
如果有多个
依然是通过
只需要设置
安装依赖:
修改
2
这样就可以在项目中使用
Understanding
JavaScript’s async await
Async/Await
- Best Practices in Asynchronous Programming
异步操作和
Async 函数
文章首发于我的博客:chenhuichao.com
刚出来不久的 ES8 包含了
async函数,它的出现,终于让 JavaScript 对于异步操作有了终极解决方案。No more callback hell。
async函数是
Generator函数的语法糖。使用
关键字
async来表示,在函数内部使用
await来表示异步。
想较于 Generator,
Async函数的改进在于下面四点:
* 内置执行器。Generator 函数的执行必须依靠执行器,而
Aysnc函数自带执行器,调用方式跟普通函数的调用一样
* 更好的语义。
async和
await相较于
*和
yield更加语义化
* 更广的适用性。
co模块约定,
yield命令后面只能是
Thunk 函数或 Promise对象。而
async函数的
await命令后面则可以是
Promise 或者 原始类型的值(Number,string,boolean,但这时等同于同步操作)
* 返回值是 Promise。
async函数返回值是 Promise 对象,比 Generator 函数返回的
Iterator 对象方便,可以直接使用
then()方法进行调用
Async 与其他异步操作的对比
先定义一个 Fetch 方法用于获取 github user 的信息:function fetchUser() { return new Promise((resolve, reject) => { fetch('https://api.github.com/users/superman66') .then((data) => { resolve(data.json()); }, (error) => { reject(error); }) }); }1
2
3
4
5
6
7
8
9
10
Promise 方式
/** * Promise 方式 */ function getUserByPromise() { fetchUser() .then((data) => { console.log(data); }, (error) => { console.log(error); }) } getUserByPromise();1
2
3
4
5
6
7
8
9
10
11
12
Promise 的方式虽然解决了 callback hell,但是这种方式充满了 Promise的
then()方法,如果处理流程复杂的话,整段代码将充满
then。语义化不明显,代码流程不能很好的表示执行流程。
Generator 方式
/** * Generator 方式 */ function* fetchUserByGenerator() { const user = yield fetchUser(); return user; } const g = fetchUserByGenerator(); const result = g.next().value; result.then((v) => { console.log(v); }, (error) => { console.log(error); })1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Generator 的方式解决了 Promise 的一些问题,流程更加直观、语义化。但是 Generator 的问题在于,函数的执行需要依靠执行器,每次都需要通过
g.next()的方式去执行。
async 方式
/** * async 方式 */ async function getUserByAsync(){ let user = await fetchUser(); return user; } getUserByAsync() .then(v => console.log(v));1
2
3
4
5
6
7
8
9
async函数完美的解决了上面两种方式的问题。流程清晰,直观、语义明显。操作异步流程就如同操作同步流程。同时
async函数自带执行器,执行的时候无需手动加载。
语法
async 函数返回一个 Promise 对象async函数内部 return 返回的值。会成为
then方法回调函数的参数。
async function f() { return 'hello world' }; f().then( (v) => console.log(v)) // hello world1
2
3
4
如果
async函数内部抛出异常,则会导致返回的 Promise 对象状态变为
reject状态。抛出的错误而会被
catch方法回调函数接收到。
async function e(){ throw new Error('error'); } e().then(v => console.log(v)) .catch( e => console.log(e));1
2
3
4
5
async 函数返回的 Promise 对象,必须等到内部所有的 await 命令的 Promise 对象执行完,才会发生状态改变
也就是说,只有当
async函数内部的异步操作都执行完,才会执行
then方法的回调。
const delay = timeout => new Promise(resolve=> setTimeout(resolve, timeout)); async function f(){ await delay(1000); await delay(2000); await delay(3000); return 'done'; } f().then(v => console.log(v)); // 等待6s后才输出 'done'1
2
3
4
5
6
7
8
9
正常情况下,await 命令后面跟着的是 Promise ,如果不是的话,也会被转换成一个 立即 resolve 的 Promise
如下面这个例子:
async function f() { return await 1 }; f().then( (v) => console.log(v)) // 11
2
3
4
如果返回的是 reject 的状态,则会被
catch方法捕获。
Async 函数的错误处理
async函数的语法不难,难在错误处理上。
先来看下面的例子:
let a; async function f() { await Promise.reject('error'); a = await 1; // 这段 await 并没有执行 } f().then(v => console.log(a));1
2
3
4
5
6
如上面所示,当
async函数中只要一个
await出现
reject 状态,则后面的
await都不会被执行。
解决办法:可以添加
try/catch。
// 正确的写法 let a; async function correct() { try { await Promise.reject('error') } catch (error) { console.log(error); } a = await 1; return a; } correct().then(v => console.log(a)); // 11
2
3
4
5
6
7
8
9
10
11
12
13
如果有多个
await则可以将其都放在
try/catch中。
如何在项目中使用
依然是通过 babel来使用。
只需要设置
presets为
stage-3即可。
安装依赖:
npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime1
修改
.babelrc:
"presets": ["es2015", "stage-3"], "plugins": ["transform-runtime"]1
2
这样就可以在项目中使用
async函数了。
Further Reading
UnderstandingJavaScript’s async await
Async/Await
- Best Practices in Asynchronous Programming
异步操作和
Async 函数
文章首发于我的博客:chenhuichao.com
相关文章推荐
- Thread,ThreadPool,Task, 到async await 的基本使用方法和理解
- 理解 JavaScript 的 async/await
- 快速理解和使用 ES7 await/async
- 理解异步之美:Promise与async await(一)
- nodejs-typescipt-Promise代码实例讲解,看完就理解async和await了
- .Net 4.5 的async 和await 的简单理解使用
- 理解ES7中的async/await
- 理解JavaScript的async/await
- async/await的实质理解
- async和await理解代码
- 深入理解 JavaScript 异步系列(5)—— async await
- C# 正确理解 async 与 await
- 理解 JavaScript 的 async/await(转)
- 理解 async/await
- await和async更多的理解
- 理解Koa2中的async&await的用法
- 关于 async 与 await的个人理解
- 理解异步之美:Promise 与 async await(二)
- ES7前端异步玩法:async/await理解
- 理解 JavaScript 的 async/await