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 ...
随机推荐
- 牛客国庆集训派对Day7 Solution
A Relic Discovery 水. #include <bits/stdc++.h> using namespace std; int t, n; int main() { s ...
- 通过Python来操作kylin
起因: 老大要求的数据,无法通过kylin里面的SQL查询到,只能通过调用接口来实现需求 第一步,安装依赖的包(py2/py3都支持,我这边用的是py2) pip install kylinpy pi ...
- react headtop title 截取
render() { const nav = this.props.nav const text = nav && nav.length > 5 ? this.strHandle ...
- SQL学习笔记三(补充-1)之MySQL存储引擎
阅读目录 一 什么是存储引擎 二 mysql支持的存储引擎 三 使用存储引擎 一 什么是存储引擎 mysql中建立的库===>文件夹 库中建立的表===>文件 现实生活中我们用来存储数据的 ...
- Hmtl5 <input>中placeholder属性(新属性)
Hmtl5 <input>中placeholder属性(新属性) 一.定义和用法 placeholder 属性提供可描述输入字段预期值的提示信息(hint). 该提示会在输入字段为空时显示 ...
- ubuntu 18.04 64bit如何编译安装内核
1.获取 wget http://mirrors.163.com/kernel/v4.x/linux-4.15.13.tar.gz 2.解压 tar xvf linux-4.15.13.tar.gz ...
- 【P4语言学习】Parser解析器
参考文章:王垠:谈谈Parser 簡單介紹 P4 語言(一)- Parser 什么是Parser 传统的parser,一般出现在编译器和编译原理课程中,援引<谈谈Parser>的定义: 首 ...
- 比较两个JSON字符串是否完全相等
RT,比较两个JSON字符串是否完全相等,这里使用google贡献的Gson. 一,no POJO,即不另外创建一个简单Java类 [java] view plain copy String str1 ...
- C# 后台模块 Word 模板操作
public static string CreateWord() { //********************************************** //来自博客http://bl ...
- Java Spring-AOP中的动态代理
2017-11-10 16:17:12 AOP中有两种代理方式,分别是JDK的动态代理和CGLib的动态代理. JDK的动态代理 Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创 ...