概念
和Generator的区别
// 使用Genrator函数 完成文件读取
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());
};
// 使用async/await
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,把yield换成了await/
对Generator的改进
- 内置执行器
Generator函数的执行必须依赖co模块。
async函数不需要,调用方式和普通函数一致,后加一个括号即可。调用之后,就会自动执行,输出最后结果。
- 更好的语义
async和await,语义更加清楚了。async表示函数内有异步操作。 await 表示紧跟在后面的表达式需要等待结果。
- 返回值是Promise
Generator函数的返回值是遍历器对象,async函数的返回值是Promise。
- 更广的适用性
co模块规定,yield后只能是Thunk函数,或者Promise对象。
但是await之后可以是Promise和基本类型的值,基本类型的值会自动调用Promise.resolvd()转化为resolved状态的Promise。
基本用法
async函数返回一个Promise对象,可以适用then方法添加回调函数,当函数执行的时候,一旦遇到await就先返回,等到异步操作完成,再接着执行函数体内后面的语句。
async function getStockPriceByName(name) {
const symbol = await getStockSymbol(name);
const stockPrice = await getStockPrice(symbol);
return stockPrice;
}
getStockPriceByName('goog').then(function (result) {
console.log(result);
});
语法
返回Promise对象
async函数返回一个Promiseu对象,函数体内的return语句返回的值,会称为then方法的参数。
如果函数体内抛出错误,会导致返回的Promise对象变为reject状态,抛出的错误对象会被catch方法回调函数或者onRejected接收到。
Promise对象的状态变化
async函数返回的Promise对象,必须等到内部所有的await命令后面的Promise对象执行完,才会发生状态变化。
也是说async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
await 命令
正常情况下 await后面是一个Promise对象,返回该对象的结果。如果不是Promise对象,就直接返回对应的值。
另一种情况,await命令后面是一个thenable对象,即定义then方法的对象,那么await会将其等同于Promise对象。
如果await命令后面的Promise对象如果变为rejected状态,则reject的参数会被catch方法的回调函数接收到。
async function f() {
await Promise.reject('出错了');//这是一个rejected状态的 Promise
//
}
f()
.then(v => console.log(v),e => console.log(e))
.catch(e => console.log(e))
// 出错了
// await语句没有return 但是reject方法的参数依然传入了catch方法,这里如果在await前面加上return
// 效果是一样的
任何一个await语句后的Promise对象变为reject状态,那么整个async函数都会被中断执行。
如何避免这种情况:我们希望 尽管出错,也要继续执行
使用try..catch语句包裹await语句,处理可能出现的错误
错误处理
如果await后面的异步操作出错,那么等同于async函数返回的Promise对象被reject。
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
// f()执行之后 会返回一个Promise
console.log(f())
// throw出来的错误会导致catch方法后面的回调函数被调用,参数就是抛出的错误对象
f()
.then(v => console.log(v))
.catch(e => console.log(e))
浏览器中执行:
防止出错的方法,是使用try..catch语句。如果有多个命令,可以统一放在try..catch语句中。
使用注意点
- 最好将await命令使用try...catch包裹
- 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
- await命令只能用在async函数中。