引言
几个简单的例子帮助理解async和await。
一、async
顾名思义,async是异步的意思,当然仅仅知道它是异步的意思是远远不够的,直接上例子。
//普通函数
function one(){
return 'one'
};
console.log(one());
//输出结果: one
//async函数
async function two(){
return 'two'
}
console.log(two());
//输出结果: Promise {<fulfilled>: "two"}
首先我们可以看到,async函数和普通函数的执行方式是相同的,只是结果有所区别,普通函数的执行结果是返回什么就打印什么,而async函数打印的结果是一个Promise对象,看到这个Promise对象我们是不是似曾相识,看下一个例子。
//返回promise对象的普通函数
function three(){
return new Promise(resolve=>{
resolve('three')
})
}
console.log(three());
//Promise {<fulfilled>: "three"}
我们可以发现,three函数和two函数的返回形式是一样的,也就是说async修饰的函数返回结果本质就是个fulfilled状态的Promise对象。既然async修饰的函数本质如此,那它是不是也可以进行链式操作呢,看下一个例子。
async function two(){
return 'two'
};
two().then(res=>{
console.log(res);
//输出结果: two
})
是的,由于本质一样,async函数也可以进行链式操作。
二、await
咱们也先来个顾名思义,等待的意思,那它到底在等待什么呢,我们同样先来看个例子。
//return一个promise对象模拟async函数
function one(){
return new Promise(resolve=>{
setTimeout(()=>resolve('one'),2000)
})
};
//在async函数中使用await,并用console.time计时
async function two(){
console.time('flag')
let res_one = await one();
console.timeEnd('flag')
};
two();
//输出结果: flag: 2000.622802734375 ms
我们可以看到,从console.time到console.timeEnd一共执行了2000.6ms,也就是说在执行one()时候,线程阻塞了2000.6ms才继续向下执行。显而易见,函数two中执行到await one()时,one()结果返回之前(2000ms的延时,0.6ms的执行时间),后面的语句就不会执行。
我们现在知道,在async函数内使用await执行另一个async函数时,后面的语句会等待当前语句执行完才会继续执行,那么async函数外会受到影响吗?看下面这个例子。
//return一个promise对象模拟async函数
function one(){
return new Promise(resolve=>{
setTimeout(()=>resolve('one'),2000)
})
};
//在async函数中使用await,并用console.time计时
async function two(){
console.time('flag')
let res_one = await one();
console.timeEnd('flag')
};
two();
console.log('运行');
//输出结果:
//运行
//flag: 2000.622802734375 ms
会先输出'运行'字符串,然后等待2000.6ms再打印了执行await one()的时间,从中得知,在async函数中使用await的时候不会影响async函数外的语句执行。
总结:
- async函数的本质是返回一个fulfilled状态的Promise对象,Promise对象的特性async函数基本也都有,比如then()链式操作。
- 在async函数中使用await执行其他async函数的时候,后面的语句会等当前语句执行结果返回后才会继续执行,但async函数外的语句执行不会受到影响。