🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

JavaScript async/await:异步编程的优雅解决方案

什么是async/await?

核心概念

1. async 关键字

2. await 关键字

async/await 与 Promise 的关系

基本用法

1. 简单示例

2. 多个await的顺序执行

为什么需要async/await?

解决的问题

适用场景

1. 依赖前一步结果的异步操作

2. 需要按顺序执行的异步操作

3. 处理多个异步操作(配合Promise.all)

错误处理

1. 使用try/catch

2. 与Promise的错误处理对比

注意事项

与Promise的对比总结

最佳实践

总结


img

JavaScript async/await:异步编程的优雅解决方案

什么是async/await?

async/await是JavaScript中处理异步操作的一种语法糖,它基于Promise实现,让异步代码的编写和阅读方式更接近同步代码。它本质上是Promise的语法糖,但让异步代码看起来像同步代码,大大提升了代码的可读性和可维护性。

核心概念

1. async 关键字

  • 用于声明一个函数是异步的
  • 函数返回一个Promise对象
  • 即使没有显式return,也会自动将返回值包装在Promise中
async function fetchData() {
  return 'Hello async';
}

// 返回一个Promise对象
fetchData().then(result => console.log(result)); // 输出: Hello async

2. await 关键字

  • 只能在async函数内部使用
  • 用于等待一个Promise解析或拒绝
  • 暂停async函数执行,直到Promise完成
async function getData() {
  try {
    const data = await fetchData(); // 等待Promise完成
    console.log(data);
  } catch (error) {
    console.error('获取数据出错:', error);
  }
}

async/await 与 Promise 的关系

特性 Promise async/await
本质 异步容器对象 基于Promise的语法糖
代码风格 链式调用 同步风格
错误处理 .catch() try/catch
代码可读性 相对复杂(回调地狱) 更清晰、线性化
执行流程 代码立即继续执行 函数执行暂停,直到await完成

基本用法

1. 简单示例

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}

fetchData();

2. 多个await的顺序执行

async function multipleAwaits() {
  console.log('开始执行多个await操作');
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log('第一个await完成');
  await new Promise(resolve => setTimeout(resolve, 2000));
  console.log('第二个await完成');
  return '所有await操作完成';
}

multipleAwaits().then(result => console.log(result));
// 输出顺序:
// 开始执行多个await操作
// 第一个await完成
// 第二个await完成
// 所有await操作完成

为什么需要async/await?

解决的问题

  1. 回调地狱(Callback Hell):早期的异步编程使用嵌套回调,代码难以阅读和维护
  2. Promise链式调用的局限:虽然比回调好,但条件判断和中间值传递仍然麻烦
  3. 代码可读性:async/await让异步代码看起来像同步代码,更符合人类思维
// 回调地狱(早期写法)
getData(function(a) {
  getMoreData(a, function(b) {
    getEvenMoreData(b, function(c) {
      getFinalData(c, function(result) {
        console.log(result);
      });
    });
  });
});

// Promise链式调用
getData()
  .then(a => getMoreData(a))
  .then(b => getEvenMoreData(b))
  .then(c => getFinalData(c))
  .then(result => console.log(result))
  .catch(err => console.error(err));

// async/await(推荐写法)
async function main() {
  try {
    const a = await getData();
    const b = await getMoreData(a);
    const c = await getEvenMoreData(b);
    const result = await getFinalData(c);
    console.log(result);
  } catch (err) {
    console.error(err);
  }
}

适用场景

1. 依赖前一步结果的异步操作

async function initApp(username, password) {
  try {
    const token = await login(username, password);
    const userInfo = await getUserInfo(token);
    const permissions = await getPermissions(userInfo.role);
    renderApp(permissions);
  } catch (err) {
    showError(err);
  }
}

2. 需要按顺序执行的异步操作

async function processOrder() {
  try {
    const order = await createOrder();
    const payment = await processPayment(order.id);
    const shipping = await shipOrder(order.id);
    return { order, payment, shipping };
  } catch (error) {
    console.error('订单处理失败:', error);
  }
}

3. 处理多个异步操作(配合Promise.all)

async function fetchAllData() {
  try {
    const [user, posts, comments] = await Promise.all([
      fetchUser(),
      fetchPosts(),
      fetchComments()
    ]);
    return { user, posts, comments };
  } catch (error) {
    console.error('数据获取失败:', error);
  }
}

错误处理

1. 使用try/catch

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error('请求失败');
    }
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('获取数据出错:', error);
    throw error; // 重新抛出错误,让调用方可以继续处理
  }
}

2. 与Promise的错误处理对比

  • Promise: 需要链式调用.catch()
  • async/await: 使用try/catch,更符合同步代码的错误处理习惯

注意事项

  1. await只能在async函数中使用

    // 错误用法
    const data = await fetchData(); // 会报错:await is only valid in async functions
    
    // 正确用法
    async function getData() {
      const data = await fetchData();
    }
    
  2. 多个await会按顺序执行

    • 不能并行执行,如果需要并行,使用Promise.all
    // 顺序执行(耗时 = 1000 + 2000 = 3000ms)
    const result1 = await fetchData1();
    const result2 = await fetchData2();
    
    // 并行执行(耗时 ≈ 2000ms)
    const [result1, result2] = await Promise.all([
      fetchData1(),
      fetchData2()
    ]);
    
  3. async函数总是返回Promise

    • 即使没有return,也会返回一个resolved的Promise
    • 如果函数中没有await,async函数会立即返回一个resolved的Promise
  4. 事件循环中的角色

    • async/await操作在微任务队列中处理
    • 当await一个Promise时,执行流暂停,控制权交还给事件循环
    • Promise解析完成后,async函数从暂停点继续执行

与Promise的对比总结

特点 Promise async/await
语法 链式调用 同步风格
可读性 较低(易形成回调地狱) 高(线性代码)
错误处理 .catch() try/catch
代码结构 嵌套的回调 线性流程
适用场景 简单的异步操作 依赖前一步结果的复杂流程

最佳实践

  1. 优先使用async/await:当异步操作需要按顺序执行或有较多条件判断时
  2. 错误处理:总是使用try/catch包裹await
  3. 避免嵌套:如果多个异步操作相互独立,使用Promise.all并行执行
  4. 保持函数简洁:每个async函数应专注于单一任务
  5. 处理多个异步操作:使用Promise.all、Promise.race等组合多个Promise

总结

async/await是JavaScript中处理异步操作的优雅方式,它让异步代码看起来像同步代码,大大提高了代码的可读性和可维护性。虽然它基于Promise实现,但通过提供更直观的语法,解决了早期异步编程中的"回调地狱"问题。

在实际开发中,你应该根据具体场景选择使用方式:

  • 当需要按顺序执行多个异步操作时,使用async/await
  • 当需要并行执行多个异步操作时,使用Promise.all
  • 当处理简单的异步操作时,可以使用Promise链式调用

记住:async/await不是Promise的替代品,而是Promise的语法糖。理解了这一点,你就能在项目中灵活运用这两种技术,写出更清晰、高效的异步代码。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐