ES6 中的异步函数 async/await 的概述及使用方法

ES6 中的异步函数 async/await 是一种简化异步操作的新型语法,可以在不破坏代码可读性和维护性的基础上解决回调函数和 Promise 的问题,同时提高代码执行效率和错误处理能力。本文将介绍 async/await 的基本概念、语法特点、使用场景及常见误区,并提供实例代码以供学习和参考。

一、什么是异步函数 async/await?

异步函数 async/awaitECMAScript 2017 标准新增的特性,它是基于 Promise 的规范进行的一层封装,可以更加直观和简洁地表达异步操作,减少了回调函数和 Promise 的嵌套和书写量,同时保持了异步操作的顺序和可读性。在语法层面上,使用 async 命令声明异步函数,函数内使用 await 命令等待 Promise 对象的状态变化,从而获取相应的结果。

async function asyncFunc(){
  let result = await promise;
  return result;
}

异步函数 async/await 将异步操作转化为同步操作的语法,使得代码具有更加优雅和自然的形式。但同时也需要注意其使用的限制和误区,例如 await 命令仅能在异步函数内部使用,且异步函数内部仅能包含一个 await 命令等等。

二、异步函数 async/await 的语法特点

异步函数 async/await 作为 Promise 的语法糖,它的特点主要集中在以下几个方面:

1、异步函数使用 async 命令声明

异步函数 async/await 的语法基于 async 命令进行声明,这样可以明确地表明函数的异步性质,并且函数的返回值也会被自动封装为 Promise 对象。

async function asyncFunction() {
  // ...
}

2、异步函数内部使用 await 命令等待 Promise 对象的状态变化

异步函数 async/await 内部使用 await 命令等待 Promise 对象的状态变化,当 Promise 对象状态变为 resolvedrejected 时,await 命令将返回 Promise 对象的结果或错误信息。

async function getRequest(){
  try {
    const response = await fetch(url);
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

3、异步函数返回的结果为 Promise 对象

异步函数 async/await 的返回值也会被自动封装为 Promise 对象,可以使用 then() 方法和 catch() 方法对异步操作进行相应的处理。

async function asyncFunc() {
  let result = await promise;
  return result;
}

asyncFunc().then(result => console.log(result)).catch(error => console.log(error));

4、异步函数内部不能使用 yield 命令

在异步函数 async/await 中,不能使用 yield 命令,在此处使用 yield 命令将会报错。

async function asyncFunc() {
  yield value;  // SyntaxError: Unexpected identifier
}

5、异步函数内部不能使用箭头函数

异步函数 async/await 内部不能使用箭头函数,因为这会改变 this 的指向,导致上下文环境的错误。

async function asyncFunc() {
  somePromise.then((result) => {    // Uncaught TypeError: Cannot read property 'bind' of undefined
    // ...
  });
}

三、异步函数 async/await 的使用场景

异步函数 async/await 是一种优雅和简洁的语法,可以应用于各种异步操作场景,包括网络请求、定时器、事件监听等等。在 async/await 中,可以使用 try...catch 语句捕获异步操作中的错误,并且可以使用 Promise.all() 方法实现多个异步操作的同时进行。

async function asyncFunc() {
  try {
    const result1 = await somePromise1();
    const result2 = await somePromise2();
    const result3 = await somePromise3();
    return [result1, result2, result3];
  } catch (error) {
    console.log(error);
  }
}

asyncFunc().then(result => console.log(result)).catch(error => console.log(error));

// 多个异步操作同时进行
Promise.all([somePromise1(), somePromise2(), somePromise3()]).then(values => console.log(values));

四、异步函数 async/await 的常见误区

异步函数 async/await 是一种简洁和直观的语法,但是在应用时也存在一些常见的误区,需要特别注意和避免。

1、异步函数不能在 foreach 循环中使用

在异步函数 async/await 中不能在 foreach 循环中使用,这会导致等待 Promise 状态变换的结果混淆和错误。

async function asyncFunc(items) {
  await items.forEach(async (item, index) => {    // 不应该在 foreach 循环中使用 await 命令
    const result = await someAsyncFunc(item);
    console.log(index, result);
  });
}

2、异步函数不能使用 async/await 内部再次嵌套

在异步函数 async/await 中不能套用 async/await,这会出现 Promise 的链式调用问题,从而导致性能和代码逻辑混乱。

async function asyncFunc() {
  await somePromise.then(async (result1) => {
    const result2 = await someAsyncFunc(result1);
    console.log(result2);
  });
}

3、异步函数使用 await 命令时需要注意 Promise 的 reject 处理

在异步函数 async/await 中使用 await 命令时,需要注意 Promise 对象的 reject 处理,否则会出现 TypeError 类型错误。

async function asyncFunc() {
  try {
    const result1 = await somePromise1();
    const result2 = await somePromise2();
    const result3 = await somePromise3();
    return [result1, result2, result3];
  } catch (error) {
    console.log(error.message);
  }
}

asyncFunc().then(result => console.log(result)).catch(error => console.log(error.message));

五、异步函数 async/await 的示例代码

1、异步函数进行网络请求

async function getRequest(){
  try {
    const response = await fetch(url);
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

2、异步函数进行事件监听

async function listenEvent() {
  return new Promise(resolve => {
    eventEmitter.on('event', data => {
      console.log(data);
      resolve(data);
    });
  });
}

listenEvent().then(result => console.log(result)).catch(error => console.log(error));

3、异步函数进行定时器操作

async function delay(time) {
  return new Promise(resolve => setTimeout(resolve, time));
}

async function repeatFunc(func, time, repeatCount) {
  let count = 0;
  while (count < repeatCount) {
    await delay(time);
    func();
    count++;
  }
}

repeatFunc(() => console.log('repeat'), 1000, 5);

六、总结

异步函数 async/await 是一种优雅和简洁的异步操作语法,可以有效地简化 Promise 和回调函数的代码量,同时还保持了异步操作的可读性和可维护性。在使用 async/await 时需要特别注意其限制和误区,并在实际应用中充分发挥其特点和优势,提高代码执行效率和错误处理能力。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a2b03dadd4f0e0ffac9e39


纠错反馈