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 相关文章推荐
JS控制文本框textarea输入字数限制的方法
Jun 17 Javascript
JS函数重载的解决方案
May 13 Javascript
jQuery中[attribute=value]选择器用法实例
Dec 31 Javascript
原生JS封装Ajax插件(同域、jsonp跨域)
May 03 Javascript
基于jQuery实现仿百度首页选项卡切换效果
May 29 Javascript
最好用的Bootstrap fileinput.js文件上传组件
Dec 12 Javascript
webpack打包单页面如何引用的js
Jun 07 Javascript
浅谈JavaScript的innerWidth与innerHeight
Oct 12 Javascript
vue项目中使用ueditor的实例讲解
Mar 05 Javascript
AngularJS自定义表单验证功能实例详解
Aug 24 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
Nov 05 Javascript
通过JavaScript下载文件到本地的方法(单文件)
Mar 17 Javascript
.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 ftp文件上传函数(基础版)
2010/06/03 PHP
IIS安装Apache伪静态插件的具体操作图文
2013/07/01 PHP
destoon找回管理员密码的方法
2014/06/21 PHP
浅谈php中include文件变量作用域
2015/06/18 PHP
PHP经典面试题之设计模式(经常遇到)
2015/10/15 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
jquery 常用操作整理 基础入门篇
2009/10/14 Javascript
jquery ajax 检测用户注册时用户名是否存在
2009/11/03 Javascript
JQuyer $.post 与 $.ajax 访问WCF ajax service 时的问题需要注意的地方
2011/09/20 Javascript
基于jquery实现等比缩放图片
2014/12/03 Javascript
第一次接触神奇的Bootstrap网格系统
2016/07/27 Javascript
原生JS实现图片轮播与淡入效果的简单实例
2016/08/21 Javascript
jQuery动态改变多行文本框高度的方法
2016/09/07 Javascript
bootstrap快速制作后台界面
2016/12/05 Javascript
原生js实现放大镜效果
2017/01/11 Javascript
bootstrap警告框示例代码分享
2017/05/17 Javascript
JavaScript高阶函数_动力节点Java学院整理
2017/06/28 Javascript
利用Vue实现移动端图片轮播组件的方法实例
2017/08/23 Javascript
详解JavaScript基础知识(JSON、Function对象、原型、引用类型)
2018/01/16 Javascript
vue-vuex中使用commit提交mutation来修改state的方法详解
2018/09/16 Javascript
js校验开始时间和结束时间
2020/05/26 Javascript
多页vue应用的单页面打包方法(内含打包模式的应用)
2020/06/11 Javascript
[02:28]DOTA2亚洲邀请赛附加赛 RECAP赛事回顾
2015/01/29 DOTA
Python对list列表结构中的值进行去重的方法总结
2016/05/07 Python
django之常用命令详解
2016/06/30 Python
MAC中PyCharm设置python3解释器
2017/12/15 Python
Python使用zip合并相邻列表项的方法示例
2018/03/17 Python
Python装饰器的执行过程实例分析
2018/06/04 Python
女性时尚网购:Chic Me
2019/07/30 全球购物
香港连卡佛百货官网:Lane Crawford
2019/09/04 全球购物
冰淇淋店创业计划书范文
2013/12/27 职场文书
导游实习生自荐书
2014/01/28 职场文书
秋季校运会广播稿100字
2014/09/18 职场文书
开展党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
民主生活会批评与自我批评总结
2014/10/17 职场文书
新店开张宣传语
2015/07/13 职场文书