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 函数的更多相关文章

  1. 2015 前端[JS]工程师必知必会

    2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ...

  2. [ 学习路线 ] 2015 前端(JS)工程师必知必会 (2)

    http://segmentfault.com/a/1190000002678515?utm_source=Weibo&utm_medium=shareLink&utm_campaig ...

  3. mysql必知必会——GROUP BY和HAVING

    mysql必知必会——GROUP BY和HAVING 创建表结构 create table `employ_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, ...

  4. 闻道Go语言,6月龄必知必会

    大家好,我是马甲哥, 学习新知识, 我的策略是模仿-->归纳--->举一反三, 在同程倒腾Go语言一年有余,本次记录<闻道Go语言,6月龄必知必会>,形式是同我的主力语言C#做 ...

  5. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  6. 《MySQL 必知必会》读书总结

    这是 <MySQL 必知必会> 的读书总结.也是自己整理的常用操作的参考手册. 使用 MySQL 连接到 MySQL shell>mysql -u root -p Enter pas ...

  7. 《SQL必知必会》学习笔记(一)

    这两天看了<SQL必知必会>第四版这本书,并照着书上做了不少实验,也对以前的概念有得新的认识,也发现以前自己有得地方理解错了.我采用的数据库是SQL Server2012.数据库中有一张比 ...

  8. SQL 必知必会

    本文介绍基本的 SQL 语句,包括查询.过滤.排序.分组.联结.视图.插入数据.创建操纵表等.入门系列,不足颇多,望诸君指点. 注意本文某些例子只能在特定的DBMS中实现(有的已标明,有的未标明),不 ...

  9. 《MySQL必知必会》[01] 基本查询

    <MySQL必知必会>(点击查看详情) 1.写在前面的话 这本书是一本MySQL的经典入门书籍,小小的一本,也受到众多网友推荐.之前自己学习的时候是啃的清华大学出版社的计算机系列教材< ...

  10. mysql必知必会

    春节放假没事,找了本电子书mysql必知必会敲了下.用的工具是有道笔记的markdown文档类型. 下面是根据大纲已经敲完的章节,可复制到有道笔记的查看,更美观. # 第一章 了解SQL## 什么是S ...

随机推荐

  1. Codeforces Round #532 (Div. 2) Solution

    A. Roman and Browser 签到. #include <bits/stdc++.h> using namespace std; ]; int get(int b) { ]; ...

  2. 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: ...

  3. linux在线安装telnet

    平常在调试机器网络互通的时候使用到telnet,新机器一般没安装相应命令,需要我们手工安装. 下面是在线安装的方法,使用以下命令即可完成安装: yum install telnet

  4. 居于mtk芯片安卓车机系统具体流程

    一:车机系统框架  MCU 功能  电源控制  Radio 控制(RDS)  按键检测(Panel/Remote/SW)  常见信号检查(倒车/大灯/刹车)  CAN 模块通讯  ARM- ...

  5. FromBottomToTop第十二周项目博客

    FromBottomToTop第十二周项目博客 本周项目计划 设计整体架构,收集素材,制作出静态界面部分 项目进展 已完成游戏整体架构设计 已完成游戏界面.背景音乐等素材的收集 正在进行静态界面部分的 ...

  6. CentOS7.2 切换成iptables规则

    关闭firewall service firewalld stop systemctl disable firewalld.service #禁止firewall开机启动 安装iptables规则: ...

  7. HDU 5934 Bomb(tarjan/SCC缩点)题解

    思路:建一个有向图,指向能引爆对象,把强连通分量缩成一点,只要点燃图中入度为0的点即可.因为入度为0没人能引爆,不为0可以由别人引爆. 思路很简单,但是早上写的一直错,改了半天了,推倒重来才过了... ...

  8. adb 安装软件

    一.连接 adb connect 192.168.1.10 输出 connected to 二.查看设备 adb devices 输出 List of devices attached device ...

  9. redis持久化策略

    redis是内存数据库,它把数据存储在内存中,这样在加快读取速度的同时也对数据安全性产生了新的问题,即当redis所在服务器发生宕机后,redis数据库里的所有数据将会全部丢失. 为了解决这个问题,r ...

  10. Spring IOC 源码简单分析 01 - BeanFactory

    ### 准备 ## 目标 了解 Spring IOC 的基础流程 ## 相关资源 Offical Doc:http://docs.spring.io/spring/docs/4.3.9.RELEASE ...