ES6必知必会 (八)—— async 函数
async 函数
1.ES2017 标准引入了 async 函数,它是对 Generator 函数的改进 , 我们先看一个读取文件的例子:
Generator 写法是这样的 :
var fs = require('fs');
var readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) return reject(error);
resolve(data);
});
});
};
var gen = function* () {
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
async 写法如下 :
var asyncReadFile = async function () {
var f1 = await readFile('/etc/fstab');
var f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
比较发现,async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await,同时不需要co模块,更加语义化;
2.async 函数返回一个 Promise 对象,内部return语句返回的值,会成为then方法回调函数的参数;
async function f() {
return 'hello world';
}
f().then(res => console.log(res))
// "hello world"
3.async 函数返回的 Promise 对象,必须等到内部所有 await 命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到 return 语句或者抛出错误。也就是说,只有 async 函数内部的异步操作执行完,才会执行 then 方法指定的回调函数;
4.如果 async 函数内部抛出错误,会导致返回的 Promise 对象变为 reject 状态,抛出的错误对象会被catch方法回调函数接收到;
async function f() {
throw new Error('出错了');
}
f().then(
res => console.log(res),
err => console.log(err)
)
// Error: 出错了
5.await 命令后面是一个 Promise 对象。如果不是,会被转成一个立即 resolve 的 Promise 对象
async function f() {
return await 'Hello World';
}
f().then(res => console.log(res))
// 'Hello World'
上述代码中,await命令的参数是 'Hello World',它被转成 Promise 对象,并立即 resolved
6.await 命令后面的 Promise 对象如果变为reject状态,则 reject 的参数会被 catch 方法的回调函数接收到
async function f() {
await Promise.reject('出错了');
}
f().then(res => console.log(res))
.catch(err => console.log(err))
// 出错了
7.async 函数中 , 只要一个await语句后面的 Promise 变为reject,那么整个 async 函数都会中断执行;
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
f(); // 出错了
8.如果我们希望即使前一个异步操作失败,也不要中断后面的异步操作。那我们可以将第一个 await 放在 try...catch 结构里面,这样不管这个异步操作是否成功,第二个 await 都会执行;
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f().then(res => console.log(res))
// hello world
或者是 await 后面的 Promise 对象再跟一个 catch 方法,处理前面可能出现的错误:
async function f() {
await Promise.reject('出错了')
.catch(err => console.log(err));
return await Promise.resolve('hello world');
}
f()
.then(res => console.log(res))
// 出错了
// hello world
9.如果 await 后面的异步操作出错,那么等同于 asyn c函数返回的 Promise 对象被 rejected:
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
f().then(res => console.log(res))
.catch(err => console.log(err))
// Error:出错了
10.为了防止出错,做法也是将其放在try...catch代码块之中,并且如果有多个await命令,可以统一放在try...catch结构中。
async function f() {
try {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
} catch(e) {
}
return await('hello world');
}
f().then( res => console.log(res) )
// 'hello world'
11.使用 await 要注意以下几点 :
await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中
async function myFunction() {
try {
await operations();
} catch (err) {
console.log(err);
}
} // 另一种写法 async function myFunction() {
await operations()
.catch(function (err) {
console.log(err);
});
}
多个 await 命令后面的异步操作,如果不存在继发关系(即互不依赖),最好让它们同时触发,缩短程序的执行时间
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]); // 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
await 命令只能用在 async 函数之中,如果用在普通函数,就会报错
async function func(db) {
let docs = [{}, {}, {}]; // 报错
docs.forEach(function (doc) {
await db.post(doc);
});
}
ES6必知必会 (八)—— async 函数的更多相关文章
- 2015 前端[JS]工程师必知必会
2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ...
- [ 学习路线 ] 2015 前端(JS)工程师必知必会 (2)
http://segmentfault.com/a/1190000002678515?utm_source=Weibo&utm_medium=shareLink&utm_campaig ...
- mysql必知必会——GROUP BY和HAVING
mysql必知必会——GROUP BY和HAVING 创建表结构 create table `employ_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, ...
- 闻道Go语言,6月龄必知必会
大家好,我是马甲哥, 学习新知识, 我的策略是模仿-->归纳--->举一反三, 在同程倒腾Go语言一年有余,本次记录<闻道Go语言,6月龄必知必会>,形式是同我的主力语言C#做 ...
- 读书笔记汇总 - SQL必知必会(第4版)
本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...
- 《MySQL 必知必会》读书总结
这是 <MySQL 必知必会> 的读书总结.也是自己整理的常用操作的参考手册. 使用 MySQL 连接到 MySQL shell>mysql -u root -p Enter pas ...
- 《SQL必知必会》学习笔记(一)
这两天看了<SQL必知必会>第四版这本书,并照着书上做了不少实验,也对以前的概念有得新的认识,也发现以前自己有得地方理解错了.我采用的数据库是SQL Server2012.数据库中有一张比 ...
- SQL 必知必会
本文介绍基本的 SQL 语句,包括查询.过滤.排序.分组.联结.视图.插入数据.创建操纵表等.入门系列,不足颇多,望诸君指点. 注意本文某些例子只能在特定的DBMS中实现(有的已标明,有的未标明),不 ...
- 《MySQL必知必会》[01] 基本查询
<MySQL必知必会>(点击查看详情) 1.写在前面的话 这本书是一本MySQL的经典入门书籍,小小的一本,也受到众多网友推荐.之前自己学习的时候是啃的清华大学出版社的计算机系列教材< ...
- mysql必知必会
春节放假没事,找了本电子书mysql必知必会敲了下.用的工具是有道笔记的markdown文档类型. 下面是根据大纲已经敲完的章节,可复制到有道笔记的查看,更美观. # 第一章 了解SQL## 什么是S ...
随机推荐
- Codeforces Round #532 (Div. 2) Solution
A. Roman and Browser 签到. #include <bits/stdc++.h> using namespace std; ]; int get(int b) { ]; ...
- An error occurred: No action handlers found - check JMeterHome and libraries
An error occurred: No action handlers found - check JMeterHome and libraries Writing log file to: D: ...
- linux在线安装telnet
平常在调试机器网络互通的时候使用到telnet,新机器一般没安装相应命令,需要我们手工安装. 下面是在线安装的方法,使用以下命令即可完成安装: yum install telnet
- 居于mtk芯片安卓车机系统具体流程
一:车机系统框架 MCU 功能 电源控制 Radio 控制(RDS) 按键检测(Panel/Remote/SW) 常见信号检查(倒车/大灯/刹车) CAN 模块通讯 ARM- ...
- FromBottomToTop第十二周项目博客
FromBottomToTop第十二周项目博客 本周项目计划 设计整体架构,收集素材,制作出静态界面部分 项目进展 已完成游戏整体架构设计 已完成游戏界面.背景音乐等素材的收集 正在进行静态界面部分的 ...
- CentOS7.2 切换成iptables规则
关闭firewall service firewalld stop systemctl disable firewalld.service #禁止firewall开机启动 安装iptables规则: ...
- HDU 5934 Bomb(tarjan/SCC缩点)题解
思路:建一个有向图,指向能引爆对象,把强连通分量缩成一点,只要点燃图中入度为0的点即可.因为入度为0没人能引爆,不为0可以由别人引爆. 思路很简单,但是早上写的一直错,改了半天了,推倒重来才过了... ...
- adb 安装软件
一.连接 adb connect 192.168.1.10 输出 connected to 二.查看设备 adb devices 输出 List of devices attached device ...
- redis持久化策略
redis是内存数据库,它把数据存储在内存中,这样在加快读取速度的同时也对数据安全性产生了新的问题,即当redis所在服务器发生宕机后,redis数据库里的所有数据将会全部丢失. 为了解决这个问题,r ...
- Spring IOC 源码简单分析 01 - BeanFactory
### 准备 ## 目标 了解 Spring IOC 的基础流程 ## 相关资源 Offical Doc:http://docs.spring.io/spring/docs/4.3.9.RELEASE ...