1.含义
ES2017 标准引入了 async 函数,使得异步操作变得更加方便。async 函数就是 Generator 函数的语法糖。
Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。
使用Generator函数实现文件读取
//封装成Promise对象
const fs = require('fs');
const readFile = function(fileName){
return new Promise(function(resolve,reject){
fs.readFile(fileName,function(error,data){
if(error) return reject(error);
resolve(data);
})
})
}
//定义Generator函数
const gen = function*(){
const test = yield readFile('./resources/test.md');
const test1 = yield readFile('./resources/test1.md')
console.log(test.toString());
console.log(test1.toString());
}
// 手动执行Generator函数
var g = gen();
g.next().value.then(data=>{
g.next(data).value.then(data=>{
g.next(data);
})
})
使用async函数实现文件的读取
//封装成Promise对象
const fs = require('fs');
const readFile = function(fileName){
return new Promise(function(resolve,reject){
fs.readFile(fileName,function(error,data){
if(error) return reject(error);
resolve(data);
})
})
}
//定义asyncGen 函数
const asyncGen = async function(){
const test = await readFile('./resources/test.md');
const test1 = await readFile('./resources/test1.md')
console.log(test.toString());
console.log(test1.toString());
}
//运行asyncGen 函数
asyncGen();
比较之下我们会发现,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,并且在执行的时候直接调用asyncGen()就可以了。
这是因为async函数对Generator 函数进行了以下的改进。
- 内置执行器:Generator 函数执行必须依靠执行器(co模块),或者自己手动执行,而async函数自带执行器。因此可以使用asyncGen()直接调用执行
- 更容易理解的语义: async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果,相对于*和yield更容易理解。
- 返回值是Promise:async函数的返回对象是Promise对象
2.返回Promise对象
async函数返回一个Promise对象,async函数内部return语句返回的值,会成为then方法回调函数的参数。
async function f(){
return 'hello world'
}
f().then(v=>{
console.log(v)
})
async函数内部抛出错误,会导致返回的Promise对象变成reject状态
async function f(){
throw new Error('出错了')
}
f().then(v=>{},e=>{
console.log(e);
})
async函数返回的Promise对象,必须等到内部所有await命名后面的Promise对象执行完,才会发生状态改变。即只有async函数内部的异步执行操作执行完,才会执行then方法指定的回调函数。
3.await命令
await关键字必须出现在async函数中
一般来说await命令后面是一个Promise对象,返回该对象的结果,如果不是Promise对象就直接返回对应的值
async function test1(){
console.log('a');
return 'b';
}
async function test2(){
const result = await test1();
console.log(result);
}
test2();
等效于
function test1(){
return new Promise((resolve,reject)=>{
console.log('a');
resolve('b');
})
}
function test2(){
return new Promise((resolve,reject)=>{
test1().then(data=>{
const result = data;
console.log(result);
resolve()
})
})
}
test2();
任何一个await语句后面的Promise对象变成reject状态,那么整个async函数都会中断执行
如果我们希望前一个异步操作失败,也不要中断后面的异步操作,这是我们可以将await放在try…catch结构里面。
async function f(){
try{
await Promise.reject('error')
}catch(e){
}
return await Promise.resolve('hello')
}
f().then(v=>{
console.log(v);
})
如果有多个await命令后面的异步操作,可以让它们同时触发,使用Promise.all