这是我参与更文挑战的第9天,活动详情查看:更文挑战
[重学JavaScript系列文章连载中…]
async是ES2017推出的函数,也是异步编程的解决方案,字面是异步的意思,那么使用它就应该不会阻塞后面代码的执行。首先我们来看个日常用法:
// 例子1
function wait(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('延迟1s')
resolve('我执行了')
},1000)
})
}
async function run(){
console.log('开始')
let p = await wait()
console.log(p)
console.log('结束')
}
run()
// 依次输出:
// 开始
// Promise<pending>
// 我执行了
// 延迟1s
// 结束
复制代码
从例子中我们可以总结出:
- async关键字放在函数前,表示函数为异步函数
- await关键字是等待的意思,需要等后面的表达式执行结束,才往下走
- await关键字只能在async函数内部使用
知道了async/await的用法,看到单独使用async函数是什么效果。
// 例子2
async function wait(){
return 'gogo'
}
wait()
// 输出:Promise{[[PromiseStatus]]: "resolved",[[PromiseValue]]: "gogo"}
wait().then(res=>{
console.log(res) // 输出:gogo
})
复制代码
可以看出async()
函数返回的是Promise
对象,而且Promise
有个resolved
。我们可以大胆推测,当async()
函数有返回值时,会通过Promise.resolve()
函数进行封装,返回一个Promise
对象。同理,如果内部发生异常,则会使用Promsie.reject()
函数进行封装返回。
这里结合例子1的写法,也可以看出,async
函数返回的是Promise
对象,要获取返回值可以使用await
关键字,但需等待await
后面表达式执行结束返回。
了解了Async函数的基础用法,那async函数是什么呢?
async函数实际上是Generator函数的语法糖。
// 懒得写例子了,借用下阮一峰老师的例子
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);
});
});
};
const gen = function* () {
const f1 = yield readFile('/etc/fstab');
const f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
// gen函数用async函数改写,如下:
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
复制代码
可以看出,async
函数就是将Generator
函数的星号替换成async
,将yield
替换成await
,只不过async函数对Generator
函数做了改进。
- 内置执行器
Generator函数执行必须靠执行器,调用next方法,或者用co模块;而async函数自带执行器,能像普通函数一样直接执行。
- 返回值是Promise
async函数返回值是Promise对象,比而Generator函数返回的是Iterator对象方便多。
- 更好的语义
async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果
- 更广的适用性
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
这里关于Generator函数的学习,可以参考下面文章:
至此我们完成了async异步函数的学习。