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()

ES7 标准中新增的 async 函数,从目前的内部实现来说其实就是 Generator 函数的语法糖。

它基于 Promise,并与所有现存的基于Promise 的 API 兼容。

async 关键字

  1. async 关键字用于声明⼀个异步函数(如 async function asyncTask1() {...}

  2. async 会⾃动将常规函数转换成 Promise,返回值也是⼀个 Promise 对象

  3. async 函数内部可以使⽤ await

await 关键字

  1. await 用于等待异步的功能执⾏完毕 var result = await someAsyncCall()

  2. await 放置在 Promise 调⽤之前,会强制async函数中其他代码等待,直到 Promise 完成并返回结果

  3. await 只能与 Promise ⼀起使⽤

  4. await 只能在 async 函数内部使⽤

相较于 Promise,async/await有何优势?

  1. 同步化代码的阅读体验(Promise 虽然摆脱了回调地狱,但 then 链式调⽤的阅读负担还是存在的)
  2. 和同步代码更一致的错误处理方式( async/await 可以⽤成熟的 try/catch 做处理,比 Promise 的错误捕获更简洁直观)
  3. 调试时的阅读性, 也相对更友好
p1.then(()=>{
p2.then(()=>{
p3.then(()=>{})
})
})
await p1()   
await p2()
await p3()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值