(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 异步编程的一个巨大进步,使得异步代码更易于编写和理解。通过使异步代码看起来像同步代码,它提高了可读性,同时保留了异步编程的非阻塞特性。

相关推荐
花开盛夏^.^1 小时前
电脑打开多个浏览器Web窗口占用较大的运行内存的原因
前端·浏览器
weixin_307779131 小时前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
Dxy12393102161 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷1 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
馒头不想说话2 小时前
实体店老板的24小时AI运营员工,写、剪、发全自动,省下一整个团队工资
前端
nice_lcj5202 小时前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试
椒哥4 小时前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
风骏时光牛马4 小时前
生成一个AI稳定性治理及疑难问题分析标题,只需要一个标题,不需要其他的任何文本。
前端
莫西干式秃头4 小时前
用 AI + threejs 写了个浏览器里的 3D 动作游戏《武来》:砍怪、放技能、开 SU7
前端·人工智能·three.js
kyriewen4 小时前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员