likes
comments
collection
share

async/await 是什么?看完你就懂了

作者站长头像
站长
· 阅读数 14

async/await 是 JavaScript ES2017 中引入的,用于处理异步操作的语法糖,使得异步代码看起来更像是同步代码,这样可以让我们更容易理解和编写。

这个时候聪明的小朋友就发问了

之前说 Promise 就是把异步代码写的像同步,怎么 async/await 又是这么解释的,不合理吧?

其实

Promise 和 async/await 都是 JavaScript 处理异步编程的工具,确实都能使异步代码看起来更接近于同步代码的样子。

主要区别在于

Promise 需要使用 .then().catch() 方法链式调用,而 async/await 可以使用标准的 try/catch 结构处理错误,使得代码的读写更加直观。此外,async/await 使得并行的异步操作更加简洁。

我们通过6个问题来学习一下到底什么是 async/await ,怎么用?

了解 async 和 await 的基本用法

async 是一个函数的关键字,用于声明一个函数是异步的。这种函数将返回一个 Promise 对象,该对象在函数完成时解析为其返回值。

await 是一个运算符,只能在 async 函数中使用,用于等待一个 Promise 解析,并返回其解析值。这就像暂停了 async 函数的执行,直到 Promise 解析完成。

async function fetchData() {
  let response = await fetch('https://api.example.com/data');
  let data = await response.json();
  return data;
}

fetchData 函数是异步的,它使用了 await 关键字等待 fetch 方法和 response.json() 方法的完成。

如何处理 aync/await 中的错误

错误处理可以通过使用 try/catch 结构来实现。如果在 try 块中的任何 await 操作发生错误,控制权就会传递到相应的 catch 块。

async function fetchData() {
  try {
    let response = await fetch('https://api.example.com/data');
    let data = await response.json();
    return data;
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

在这段代码中,如果 fetch 或 response.json() 发生错误,这些错误将被 catch 块捕获,并在控制台上打印出来。

我们再思考一下,什么样的错误会被 catch 捕获呢?

1、如果 fetch 请求因为网络问题或其他原因失败(例如,无法连接到服务器),则 fetch 会抛出错误,这个错误可以被 catch 块捕获。

2、如果 fetch 请求成功,但是服务器返回了一个错误状态码(如 404 或 500),fetch 不会抛出错误,而是返回一个 ok 属性为 false 的 Response 对象。你需要手动检查这个状态并抛出一个错误。

3、如果 response.json() 尝试解析的响应不是有效的 JSON,它会抛出一个错误,这个错误可以被 catch 块捕获。

例如:

async function fetchData() {
  try {
    let response = await fetch('https://api.example.com/data');

    // 检查响应状态
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    let data = await response.json();
    return data;
  } catch (error) {
    console.error('An error occurred:', error);
  }
}

在这个例子中,无论是 fetch 失败,还是服务器返回错误状态,或者响应不是有效的 JSON,都会抛出一个错误,并且这个错误可以被 catch 块捕获。

async/await 和 Promise 之间的关系

async/await 是基于 Promise 的,并用于更简洁和易读的方式来处理异步操作。async 函数总是返回一个 Promise 对象,await 等待 Promise 对象解析。

如何使用 async/await 来处理并行的异步操作

当你有多个异步操作需要同时进行时,可以使用 Promise.all() 函数与 async/await 结合使用。

async function fetchDataInParallel() {
  const [data1, data2] = await Promise.all([
    fetch('https://api.example.com/data1').then(response => response.json()),
    fetch('https://api.example.com/data2').then(response => response.json())
  ]);
  console.log(data1, data2);
}

如何使用 async/await 来处理顺序的异步操作

当你需要按顺序执行多个异步操作时,可以在一个 async 函数中连续使用 await。

async function fetchDataInSequence() {
  let response1 = await fetch('https://api.example.com/data1');
  let data1 = await response1.json();
  console.log(data1);

  let response2 = await fetch('https://api.example.com/data2');
  let data2 = await response2.json();
  console.log(data2);
}

在哪些情况下应该使用 async/await,以及哪些情况下应该使用 Promise?

使用 async/await 或 Promise 主要取决于你的需求和你的代码结构。

  • 如果你的代码中有很多连续的、依赖于前一个操作结果的异步操作,使用 async/await 可能会更方便,因为它可以让你的代码看起来更接近同步代码,避免了回调地狱。
  • 如果你需要在某个异步操作完成后执行多个操作,或者需要执行多个并行的异步操作并在所有操作完成后做一些事情,使用 Promise 可能会更合适。
  • 如果你需要在发生错误时能够更精细地控制流程,比如在 catch 块中做一些清理工作或者继续抛出错误,那么 async/await 结合 try/catch 可能会更方便。

async 函数一定是异步的吗?返回结果一定是 Promise 对象吗?

使用 async 关键字定义的函数被称为异步函数。

这并不是说函数内的操作一定是异步的(你完全可以在 async 函数中只进行同步操作),而是说异步函数总是返回一个 Promise 对象,而这个 Promise 对象会根据函数的执行情况来决定是 resolve 还是 reject。

但是

异步函数(async function)总是返回一个 Promise 对象。如果异步函数的返回值不是一个 Promise 对象,那么这个返回值会被自动包装为 Promise 对象。比如:

async function foo() {
  return 'Hello, world!';
}

let p = foo();
console.log(p);  // Promise { 'Hello, world!' }

在这个例子中,foo 是一个异步函数,但它返回的是一个字符串,而不是一个 Promise。

但是,当我们调用 foo() 时,我们得到的实际上是一个 Promise 对象,这个 Promise 对象的结果就是函数返回的字符串。

这个特性使得你可以在异步函数中使用 await 关键字来等待一个 Promise 完成(或拒绝),就像你在处理同步代码一样。

转载自:https://juejin.cn/post/7234692023193190460
评论
请登录