(JavaScript)对 async/await 的理解

当涉及到 JavaScript 中的异步编程时,async/await 是一个强大而直观的工具,它使得处理异步代码更加容易理解和编写。让我们一步步地深入了解它。

1. 异步编程背景

在 JavaScript 中,某些操作可能需要一些时间来完成,比如网络请求、文件读取、定时器等。为了不阻塞程序的执行,JavaScript 使用了异步编程模型,即不等待某些操作完成,而是继续执行下面的代码。

2. Promise

在ES6中引入了 Promise 对象,用于更好地处理异步操作。但是,使用 Promise 仍然需要嵌套回调函数,导致代码可读性不佳,这就是所谓的"回调地狱"问题。

有关Promise的内容,可以看我对于promise的理解以及promise解决了什么问题这两个文章

3. async/await 的引入

为了解决回调地狱问题,ES2017(ES8)引入了 async/await。这是一种在写异步代码时更具可读性和可维护性的语法糖

什么是语法糖

"语法糖"是计算机科学中的一个概念,指的是一种在语言中添加的、对语言的语法结构进行改进,使得特定的代码模式更容易编写或更易于阅读的语法形式。语法糖并不引入新的功能,而是提供了一种更便捷、更易读的语法。

这个术语的意义在于,尽管它使得代码编写更加方便,但它本质上并没有改变语言的功能或能力。它只是一种语法层面上的改进,简化了代码的书写方式,使得开发者更容易理解和使用某些特性。

一个常见的例子是前文提到的 async/await,它被认为是 JavaScript 中的一种语法糖。使用 async/await 让异步代码看起来更像同步代码,但它本质上仍然是基于 Promise 的异步编程。

另一个例子是 Python 中的列表推导式。列表推导式提供了一种简洁的语法来创建列表,但实际上它是对常规循环的一种语法糖。

总的来说,语法糖是一种为了提高代码可读性和编写效率而引入的语法结构。

4. async 函数

async 关键字用于定义一个返回 Promise 的异步函数。使用 async 声明的函数内部,可以使用 await 关键字来暂停函数执行,等待 Promise 解决,语法上强制规定 await 只能出现在 asnyc 函数中

javascript 复制代码
async function fetchData() {
  // 异步操作,比如请求数据
  let result = await fetchDataFromServer();
  console.log(result);
}

5. await 表达式

await 只能async 函数内部使用,用于等待一个表达式解决为 Promise。当 await 后面的表达式被解决时,它返回解决的值。

javascript 复制代码
async function fetchData() {
  let result = await fetchDataFromServer();
  console.log(result);
}

// fetchDataFromServer 返回一个 Promise
function fetchDataFromServer() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Data fetched successfully!");
    }, 2000);
  });
}

// 使用
fetchData();

6. 错误处理

使用 try/catch 来处理异步函数中的错误,这比传统的回调错误处理更为直观

javascript 复制代码
async function fetchData() {
  try {
    let result = await fetchDataFromServer();
    console.log(result);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}

7. 同步化的写法

async/await 使得异步代码的写法更类似于同步代码,提高了代码的可读性和可维护性。

javascript 复制代码
async function fetchDataSequentially() {
  let result1 = await fetchDataFromServer1();
  console.log(result1);

  let result2 = await fetchDataFromServer2();
  console.log(result2);

  // ...
}

8.一些有关概念

  1. 返回 Promise 对象: async函数总是返回一个Promise对象。这是因为async函数内部使用Promise.resolve()来封装函数返回的值。无论async函数返回的是一个直接量还是一个经过Promise.resolve()包装的值,最终都会被封装成一个Promise对象。

    javascript 复制代码
    async function exampleAsyncFunction() {
      return 42;
    }
    
    const resultPromise = exampleAsyncFunction();
    console.log(resultPromise); // Promise { 42 }
  2. 无返回值情况: 如果async函数没有显式的return语句,或者return的是一个没有使用await关键字的表达式,那么该async函数会隐式返回Promise.resolve(undefined)

    javascript 复制代码
    async function exampleAsyncFunction() {
      // 没有 return 或者 return 后没有使用 await
    }
    
    const resultPromise = exampleAsyncFunction();
    console.log(resultPromise); // Promise { undefined }
  3. 无等待立即执行: 在没有await的情况下执行async函数时,它会立即执行并返回一个Promise对象。这是因为async函数内部的代码会立即执行,不会等待异步操作完成。

    javascript 复制代码
    async function exampleAsyncFunction() {
      console.log("Async function is executing");
      return 42;
    }
    
    const resultPromise = exampleAsyncFunction();
    console.log(resultPromise); // Promise { 42 }
  4. Promise.resolve(x)的简写: Promise.resolve(x)是一个用于快速将值x封装成Promise对象的方法。它是Promise构造函数的一个静态方法。你可以把它看作是new Promise(resolve => resolve(x))的简写形式,用于将字面量对象或其他对象封装成Promise实例。

    javascript 复制代码
    const value = 42;
    const promise = Promise.resolve(value);
    console.log(promise); // Promise { 42 }

总结

async/await 是 JavaScript 异步编程的一个巨大进步,使得异步代码更易于编写和理解。通过使异步代码看起来像同步代码,它提高了可读性,同时保留了异步编程的非阻塞特性。

相关推荐
转转技术团队12 分钟前
多代理混战?用 PAC(Proxy Auto-Config) 优雅切换代理场景
前端·后端·面试
南囝coding13 分钟前
这几个 Vibe Coding 经验,真的建议学!
前端·后端
gnip27 分钟前
SSE技术介绍
前端·javascript
掘金安东尼35 分钟前
蔚来 600 亿研发成本,信还是不信。。
面试·程序员·github
yinke小琪41 分钟前
JavaScript DOM节点操作(增删改)常用方法
前端·javascript
枣把儿1 小时前
Vercel 收购 NuxtLabs!Nuxt UI Pro 即将免费!
前端·vue.js·nuxt.js
望获linux1 小时前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
爱编程的喵1 小时前
从XMLHttpRequest到Fetch:前端异步请求的演进之路
前端·javascript
喜欢吃豆1 小时前
深入企业内部的MCP知识(三):FastMCP工具转换(Tool Transformation)全解析:从适配到增强的工具进化指南
java·前端·人工智能·大模型·github·mcp
豆苗学前端1 小时前
手把手实现支持百万级数据量、高可用和可扩展性的穿梭框组件
前端·javascript·面试