ES6新特性八:async函数用法实例详解
本文实例讲述了ES6新特性之async函数用法。分享给大家供大家参考,具体如下:
1.async函数是什么?
node.js版本7及之后版本才支持该函数。
可以简单的理解为他是Generator函数的语法糖,即Generator函数调用next()返回的结果。
①Generator函数需要next()或执行器进行执行,而async函数只需和普通函数一样执行。
②async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果,结果返回才会向下执行。
③async函数的返回值是Promise对象,这比Generator函数的返回值是Iterator对象方便多了。你可以用then方法指定下一步的操作。
2.async函数与Generator函数写法对比
varfs=require('fs');
//读取文件的方法
varreadFile=function(fileName){
returnnewPromise(function(resolve,reject){
fs.readFile(fileName,function(error,data){
if(error)reject(error);
resolve(data);
});
});
};
vargen=function*(){
varf1=yieldreadFile('/etc/fstab');
varf2=yieldreadFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
varasyncReadFile=asyncfunction(){
varf1=awaitreadFile('/etc/fstab');
varf2=awaitreadFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
3.async函数的作用?
在异步程序中(比如在nodejs),在下一步程序中,需要异步返回的结果,由于是异步,下一步会在异步返回前就会执行完,这时程序就会出现不是我们预想的结果。而async函数就可以很好的解决这一问题。我们将异步操作放在await后面,等待异步返回了结果程序才会向下执行。
举例:
/**
*CreatedbyDasonon2017/3/12.
*/
varmysql=require('mysql');
varpool=mysql.createPool({
host:'127.0.0.1',
user:'root',
password:'root',
database:'dason',
multipleStatements:true
});
//查询所有id的方法
vargetResult=function(){
returnnewPromise(function(resolve,reject){
pool.getConnection(function(err,connection){
if(err){
console.log(err);
throwerr;
}
connection.query('SELECTidFROMuser',function(err,result){
if(err){
//console.log(err);
throwerr;
//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
varupdateName=function(id){
pool.getConnection(function(err,connection){
if(err){
console.log(err);
}
connection.query("updateusersetname='A'whereid=?",[id],function(err,result){
if(err){
console.log(err);
}
connection.release();
});
});
};
asyncfunctionupdate(){
/**
*getResult是一个异步函数,放在await后面,
*当函数执行的时候,一旦遇到await就会先返回,
*等到异步操作完成,将异步结果返回,再接着执行函数体内后面的语句。
*/
varresult=awaitgetResult();
console.log("result:"+JSON.stringify(result));
//result:[{"id":1},{"id":2},{"id":4},{"id":5},{"id":6},{"id":3},{"id":7}]
for(constobjofresult){
updateName(obj.id);
}
}
update();//async函数调用和普通方法一样
4.语法
①async函数返回一个promise对象。
②async函数内部return语句返回的值,会成为then方法回调函数的参数。
③async函数的await命令后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作),如果不是Promise对象,会被转成一个立即resolve的Promise对象。
asyncfunctionf(){
return'helloworld';//会自动调用Promise.resolve('helloworld'),将其转化为promise对象
}
f().then(v=>console.log(v))
//"helloworld"
asyncfunctionf(){
thrownewError('出错了');
}
f().then(
v=>console.log(v),
e=>console.log(e)
)
//Error:出错了
④async函数返回的Promise对象,必须等到内部所有await命令后面的Promise对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
注意1:await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
asyncfunctionmain(){
try{
varval1=awaitfirstStep();
varval2=awaitsecondStep(val1);
varval3=awaitthirdStep(val1,val2);
console.log('Final:',val3);
}
catch(err){
console.error(err);
}
}
⑤await命令后面的Promise对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。
asyncfunctionf(){
awaitPromise.reject('出错了');//没有return,即不是async函数返回的promise对象,也会被catch方法的回调函数接收到
}
f()
.then(v=>console.log(v))
.catch(e=>console.log(e))
//出错了
注意2:多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。不然会增加耗时。
//耗时写法 letfoo=awaitgetFoo(); letbar=awaitgetBar(); //同时触发 //写法一 let[foo,bar]=awaitPromise.all([getFoo(),getBar()]); //写法二 letfooPromise=getFoo(); letbarPromise=getBar(); letfoo=awaitfooPromise; letbar=awaitbarPromise;
希望本文所述对大家ECMAScript程序设计有所帮助。