async和await的基本使用和特性

453 阅读2分钟

引言

几个简单的例子帮助理解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函数外的语句执行。

总结:

  1. async函数的本质是返回一个fulfilled状态的Promise对象,Promise对象的特性async函数基本也都有,比如then()链式操作。
  2. 在async函数中使用await执行其他async函数的时候,后面的语句会等当前语句执行结果返回后才会继续执行,但async函数外的语句执行不会受到影响。