async
简单介绍,就是一个语法糖。关于Generator函数改进的语法糖
const myGenerator = function* (){
let fn1 = yield 1 + 2;
let fn2 = yield 2 + 2;
return `fn1: ${
fn1}, fn2: ${
fn2}`
}
// 用async语法糖
const asyncFn = async function(){
let fn1 = await 1 + 2;
let fn2 = await 2 + 2;
return `fn1: ${
fn1}, fn2: ${
fn2}`
}
改进体现:
- 内置执行器
Generator函数的执行须要靠执行器next方法,而async函数自带执行器。可以做到自动执行。
- 语义明了
async和await,async表示函数中存在异步操作,await表示后面的表达式需要等待结果。
- 适用性广
await命令的后面可以是原始数据类型和Promise对象,最终都是转换成一个resolved状态下的Promise对象
- 返回值可链式操作
async函数的返回值是Promise对象,也就意味着可以使用then方法进行下一步操作。而Generator函数的返回值是Iterator对象。
基本使用
async函数后面可继续使用then方法添加回调函数。函数执行时遇到await就会等待await后面表达式的返回值再执行后续的语句。
async function myAsync(value) {
let timing = await new Promise((resolve) => {
return setTimeout(resolve, 2000);
});
console.log(value);
}
myAsync('hi shaoin');
await 命令
一般await命令的后面是一个Promise对象,返回该对象的结果,不知Promise对象就会直接返回值。
实现休眠效果
function needSleep(time){
return new Promise(resolve =>{
setTimeout(resolve,time);
})
}
async function systemFn(){
for (let i = 5; i >0; i--){
console.log(i);
await needSleep(2000);
}
}
systemFn()
也就是在定时器(异步方法)的基础上,使用Promise封装成同步的代码,确定具备定时器的效果
错误处理
await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。
async function myError(){
try {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
} catch(e) {
console.log(e)
}
return await('complate');
}
用try…catch为了防止错误被外界捕获,进而终止函数内部的执行进程。
注意的点
await
命令后面的Promise
对象,运行结果可能是rejected
,所以最好把await
命令放在try...catch
代码块中。- 多个
await
命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。因为继发关系比较耗时
// 处理 非继发关系的方法
let [getOne, gettwo] = await Promise.all([getOne(), getTwo()]);
let getOnePromise = getOne();
let getTwoPromise = getTwo();
let getOne = await getOnePromise;
let getTwo = await getTwoPromise;
await
只能使用在async
函数中,在普通函数中会报错。async
函数可以保留运行堆栈。
let fn1 = ()=>{
fn2().then(()=>{
fn3()
})
}
// 如果fn2()或fn3()报错,错误堆栈将不包括fn1()。
let fn1 = async()=> {
await fn2();
fn3();
}
// 因为 fn2()在运行的时候,fn1()是暂停的状态,所以上下文环境是保存状态。
// 如果fn2()或fn3()报错,错误堆栈将包括fn1()。
参考文献
阮一峰老师的 ECMAScript 6 入门