async函数

async函数

基本概念

async 函数是什么?一句话,它就是 Generator 函数的语法糖。

将上一章的代码改成 async 函数的版本:

const { promisify } = require("util");
const path = require('path')
const file1 = path.join(__dirname, './text/1.txt')
const file2 = path.join(__dirname, './text/2.txt')
const readFileP = promisify(readFile)

function* f() {
  let data1 = yield readFileP(file1)
  console.log('耶,完成了1,数据是' + data1);
  let data2 = yield readFileP(file2)
  console.log('耶,完成了2,数据是' + data2);
}

//async函数的版本
async function f() {
  let data1 = await readFileP(file1)
  console.log('耶,完成了1,数据是' + data1);
  let data2 = await readFileP(file2)
  console.log('耶,完成了2,数据是' + data2);
}

比较后就会发现,async函数的版本就是将 Generator 函数的星号(*)替换成async,将yield替换成await

定义async函数

使用async关键字定义一个async函数:

async function f() {
  let data1 = await readFileP(file1)
  console.log('耶,完成了1,数据是' + data1);
  let data2 = await readFileP(file2)
  console.log('耶,完成了2,数据是' + data2);
}

执行async函数

执行async函数则相当于执行了一个自动运行的Generator函数,async函数如果返回的结果不是Promise,则会运行结果包装成一个Promise返回:

async function f() {
  console.log(1);
}
f().then(()=>{
  console.log(2);
})

async function f() {
  console.log(1);
  return 'done'
}

f().then(value => {
  console.log(value);
})

await关键字

yield类似,async函数中可以使用await关键字,await关键字后面一般会写一个Promise实例,async函数执行的过程中,每次遇到await关键字,会将控制权转回外部环境

  1. 如果await后面是Promise实例,则会等到该 Promise实例被resolve后,才会把本次await到下次await之间的代码推到MircoTask(微任务)中等待执行,并且await的返回值是该Promise实例resolve的值
  2. 如果await后面不是Promise实例,则会立即将本次await到下次await之间的代码推到MircoTask(微任务)中等待执行,并且await的返回值是等于await后面表达式的值:
async function f() {
  let data = await new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('a')
    }, 2000)
  })
  console.log(data);
}

//f()
//console.log('end')

如果await后面不是Promise 实例

async function f() {
  let data = await 'a'
  console.log(data);
}
f()
console.log('end'); 
//end
//a

async函数的错误处理

如果Promise被reject或抛出错误,await之后的代码不会执行,因此,需要使用try..catchawait进行错误捕捉:

async function f() {
  try {
    let data = await new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('123')
      }, 2000)
    })
    //后续代码无法执行
    console.log('done');
  }catch (e) {
    console.log('发生错误:',e);
  }
}
f()

async函数处理并发异步任务

如果,async函数中的每个await都是等到前面await resolve后才会执行,如果想并发执行,可以使用Promise.all:

/*并发处理异步*/
async function f() {
  let time1 = new Date()
  let [data1,data2] = await Promise.all([
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('123')
      }, 2000)
    }),
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('123')
      }, 3000)
    })
  ])
  console.log(data1,data2,'用时:'+ (new Date() - time1));
}
f()

async函数与Promise的对比

async函数写异步逻辑相比Promise会更加简洁,在处理不同异步结果相互依赖,错误处理,if...else分支等情况时更加简便:

const {readFile} = require('fs')
const { promisify } = require("util");
const path = require('path')
const file1 = path.join(__dirname, './text/1.txt')
const file2 = path.join(__dirname, './text/2.txt')
const file3 = path.join(__dirname, './text/3.txt')
const readFileP = promisify(readFile)

function f1() {
  readFileP(file1).then(data1 =>{
    console.log('耶,完成了1,数据是' + data1);
    return readFileP(file2)
  }).then(data2 => {
    console.log('耶,完成了1,数据是' + data2);
    return readFileP(file3)
  }).then(data3 => {
    console.log('耶,完成了1,数据是' + data3);
  })
}

async function f2() {
  let data1 = await readFileP(file1)
  console.log('耶,完成了1,数据是' + data1);
  let data2 = await readFileP(file2)
  console.log('耶,完成了2,数据是' + data1 + data2);
  let data3 = await readFileP(file3)
  console.log('耶,完成了2,数据是' + data1 + data2 + data3);

}
f()
原文地址:https://www.cnblogs.com/xm0328/p/14128001.html