ES6新特性八:async函数用法实例详解


Posted in Javascript onApril 21, 2017

本文实例讲述了ES6新特性之async函数用法。分享给大家供大家参考,具体如下:

1. async 函数是什么?

node.js 版本7及之后版本才支持该函数。

可以简单的理解为他是Generator 函数的语法糖,即Generator 函数调用next() 返回的结果。

Generator 函数需要next() 或执行器进行执行,而async 函数只需和普通函数一样执行。

asyncawait,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果,结果返回才会向下执行

async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

2. async 函数与Generator 函数写法对比

var fs = require('fs');
//读取文件的方法
var readFile = function (fileName) {
 return new Promise(function (resolve, reject) {
 fs.readFile(fileName, function(error, data) {
  if (error) 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());
};
var asyncReadFile = async function () {
 var f1 = await readFile('/etc/fstab');
 var f2 = await readFile('/etc/shells');
 console.log(f1.toString());
 console.log(f2.toString());
};

3. async 函数的作用?

在异步程序中(比如在nodejs),在下一步程序中,需要异步返回的结果,由于是异步,下一步会在异步返回前就会执行完,这时程序就会出现不是我们预想的结果。而async 函数就可以很好的解决这一问题。我们将异步操作放在await 后面,等待异步返回了结果程序才会向下执行。

举例:

/**
 * Created by Dason on 2017/3/12.
 */
var mysql = require('mysql');
var pool = mysql.createPool({
 host : '127.0.0.1' ,
 user : 'root' ,
 password : 'root' ,
 database : 'dason',
 multipleStatements: true
});
//查询所有id的方法
var getResult = function () {
 return new Promise(function(resolve,reject){
  pool.getConnection(function(err,connection){
   if(err){
    console.log(err);
    throw err;
   }
   connection.query('SELECT id FROM user',function(err,result){
    if(err){
     //console.log(err);
     throw err;
     //reject(err);
    }
    console.log(result);
    //[{id:1},{id:2},{id:4},{id:5},{id:6},{id:3},{id:7}]
    connection.release();
    resolve(result);
   });
  });
 });
};
//将所有人的name 改为 A
var updateName = function(id) {
 pool.getConnection(function(err,connection){
  if(err){
   console.log(err);
  }
  connection.query("update user set name='A' where id = ?",[id],function(err,result){
   if(err){
    console.log(err);
   }
   connection.release();
  });
 });
};
async function update() {
 /**
  * getResult 是一个异步函数,放在await 后面,
  * 当函数执行的时候,一旦遇到await就会先返回,
  * 等到异步操作完成,将异步结果返回,再接着执行函数体内后面的语句。
  */
 var result = await getResult();
 console.log("result:"+JSON.stringify(result));
 //result:[{"id":1},{"id":2},{"id":4},{"id":5},{"id":6},{"id":3},{"id":7}]
 for(const obj of result){
  updateName(obj.id);
 }
}
update();// async函数调用和普通方法一样

4. 语法

① async 函数返回一个promise 对象。

② async函数内部return语句返回的值,会成为then方法回调函数的参数。

③ async函数的await命令后面,可以是Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作),如果不是Promise 对象,会被转成一个立即resolve的 Promise 对象。

async function f() {
 return 'hello world';//会自动调用Promise.resolve('hello world'),将其转化为promise对象
}
f().then(v => console.log(v))
// "hello world"
async function f() {
 throw new Error('出错了');
}
f().then(
 v => console.log(v),
 e => console.log(e)
)
// Error: 出错了

④ async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数

注意1await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中

async function main() {
 try {
 var val1 = await firstStep();
 var val2 = await secondStep(val1);
 var val3 = await thirdStep(val1, val2);
 console.log('Final: ', val3);
 }
 catch (err) {
 console.error(err);
 }
}

⑤ await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。

async function f() {
 await Promise.reject('出错了');//没有return,即不是async函数返回的promise对象,也会被catch方法的回调函数接收到
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

注意2:多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。不然会增加耗时。

//耗时写法
let foo = await getFoo();
let bar = await getBar();
//同时触发
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;

希望本文所述对大家ECMAScript程序设计有所帮助。

Javascript 相关文章推荐
刷新页面实现方式总结(HTML,ASP,JS)
Nov 13 Javascript
IE6弹出“已终止操作”的解决办法
Nov 27 Javascript
js自动生成的元素与页面原有元素发生堆叠的解决方法
Sep 04 Javascript
浅析jquery unbind()方法移除元素绑定的事件
May 24 Javascript
喜大普奔!jQuery发布 3.0 最终版
Jun 12 Javascript
封装获取dom元素的简单实例
Jul 08 Javascript
jQuery实现的简单拖动层示例
Feb 22 Javascript
JS字符串按逗号和回车分隔的方法
Apr 25 Javascript
深入Node TCP模块的理解
Mar 13 Javascript
微信小程序实现批量倒计时功能
Nov 01 Javascript
Nuxt配置Element-UI按需引入的操作方法
Jul 06 Javascript
Jquery $.map使用方法实例详解
Sep 01 jQuery
.net MVC+Bootstrap下使用localResizeIMG上传图片
Apr 21 #Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
Apr 21 #jQuery
ES6新特性七:数组的扩充详解
Apr 21 #Javascript
React中ES5与ES6写法的区别总结
Apr 21 #Javascript
ES6新特性六:promise对象实例详解
Apr 21 #Javascript
ES6新特性五:Set与Map的数据结构实例分析
Apr 21 #Javascript
webpack配置的最佳实践分享
Apr 21 #Javascript
You might like
PHP的自定义模板引擎
2017/03/24 PHP
Laravel 创建指定表 migrate的例子
2019/10/09 PHP
分享精心挑选的23款美轮美奂的jQuery 图片特效插件
2012/08/14 Javascript
jquery 按钮状态效果 正常、移上、按下
2013/08/12 Javascript
jQuery通过扩展实现抖动效果的方法
2015/03/11 Javascript
js控制网页前进和后退的方法
2015/06/08 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
轻松搞定jQuery.noConflict()
2016/02/15 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
JavaScript实现的微信二维码图片生成器的示例
2016/10/26 Javascript
JavaScript Base64 作为文件上传的实例代码解析
2017/02/14 Javascript
原生JS实现 MUI导航栏透明渐变效果
2017/11/07 Javascript
Vue使用NProgress的操作过程解析
2019/10/10 Javascript
javascript设计模式 ? 简单工厂模式原理与应用实例分析
2020/04/09 Javascript
js制作提示框插件
2020/12/24 Javascript
[44:26]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第二局
2016/03/03 DOTA
Python切片用法实例教程
2014/09/08 Python
bluepy 一款python封装的BLE利器简单介绍
2019/06/25 Python
解决django后台管理界面添加中文内容乱码问题
2019/11/15 Python
python分布式计算dispy的使用详解
2019/12/22 Python
浅析Python 条件控制语句
2020/07/15 Python
详解html5 canvas常用api总结(二)--绘图API
2016/12/14 HTML / CSS
Paradigit比利时电脑卖场:购买笔记本、电脑、平板和外围设备
2016/11/28 全球购物
英国高档百货连锁店:John Lewis
2017/11/20 全球购物
日本乐天官方海外转运服务:Rakuten Global Express
2018/11/30 全球购物
如何获取某个日期是当月的最后一天
2013/12/05 面试题
判断单链表中是否存在环
2012/07/16 面试题
销售代表求职自荐信
2013/10/01 职场文书
医科大学生的自我评价
2013/12/04 职场文书
参观监狱心得体会
2014/01/02 职场文书
如何写自我鉴定
2014/03/19 职场文书
2014年小学教研工作总结
2014/12/06 职场文书
2014年终工作总结范本
2014/12/15 职场文书
博士生专家推荐信
2015/03/25 职场文书
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis
Redis安装使用RedisJSON模块的方法
2022/03/23 Redis