js async/await函数
async
函数就是generator
函数的语法糖,一般结合Promise
使用
我们可以把generator函数函数改写成async/await函数,例如
var fs = require('fs');
var co = require('co');
var readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function (error, data) {
if (error) reject(error);
resolve(data.toString());
});
});
};
function* read() {
// resolve multiple promises in parallel
var a = yield readFile('./data/a.text')
var b = yield readFile('./data/b.text')
console.log(a.toString());
console.log(b.toString());
}
co(read)
改写成
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.toString());
});
});
};
async function read() {
// resolve multiple promises in parallel
var a = await readFile('./data/a.text')
var b = await readFile('./data/b.text')
console.log(a.toString());
console.log(b.toString());
}
read()
输出和上面的generator
函数是一样的,但是我们对比可以发现,async
函数只是将generator
函数的*
去掉了,然后在前面加了一个async
,函数内部的yield
替换成了await
,其他的都没有变化
async
函数的改进,体现在以下几点:
- 内置执行器:我们发现是用
async
函数,我们不需要引入co
模块,就能使用,因为async
函数内置了执行器 - 更好的语义:
async/await
相比generator
的yield
有更好的语义,async
表示函数内部有异步操作,而await
表示紧跟在后面的表达式需要等待结果,才能继续执行下面的代码 - 更广的适用性:
co
模块约定,yield
命令后面只能是thunk
函数或Promise
对象,而async
函数的await
命令后面,可以是Promise
对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即resolved
的Promise
对象)。 - 返回值是
Promise
:async
函数的返回值是Promise
对象,这比generator
函数的返回值是iterator
对象方便多了。你可以用then
方法指定下一步的操作。
async
函数的返回值是一个Promise
对象,函数内部return
语句返回的值,会成为then
方法回调函数的参数。
async function fn() {
return 123
}
fn().then(d => console.log(d)) // 123
错误处理
async函数的错误处理方式可以放在函数内部也可以放在函数外部
放在函数内部
async function f() {
try {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
} catch(e) {
}
return await('hello world');
}
放在函数外部
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
如果有多个await命令,可以统一放在try…catch结构中。
async function f() {
try {
const val1 = await firstStep();
const val2 = await secondStep(val1);
const val3 = await thirdStep(val1, val2);
console.log('Final: ', val3);
}
catch (err) {
console.error(err);
}
}
思考一下下面的代码为什么会按照1、3、2
的顺序输出,那是因为执行fn
函数,执行console.log(1)
,然后返回一个Promise
对象,又由于Promise
对象的then
属于微任务,放到微任务执行队列里面,执行下面的console.log(3)
,后面执行栈没有代码了,然后执行微任务队列里的任务,执行console.log(2)
async function fn() {
console.log(1)
return 2
}
fn().then(d => console.log(d))
console.log(3)
输出结果
1
3
2
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com