详解 async/await :应用场景,示例代码,注意事项

还是大剑师兰特:曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,echarts等技术开发,欢迎加底部微信(gis-dajianshi),一起交流。

在这里插入图片描述

No.内容链接
1Openlayers 【入门教程】 - 【源代码+示例300+】
2Leaflet 【入门教程】 - 【源代码+图文示例 150+】
3Cesium 【入门教程】 - 【源代码+图文示例200+】
4MapboxGL【入门教程】 - 【源代码+图文示例150+】
5前端就业宝典 【面试题+详细答案 1000+】

在这里插入图片描述


async/await 是 JavaScript 异步编程的一种简化写法,它建立在 Promise 基础之上,提供了更加简洁和易于理解的方式来处理异步操作。以下是 async/await 的关键字、应用场景、示例代码以及注意事项。

一、关键字

  1. async 关键字:

    • async 关键字用于声明一个函数为异步函数。
    • 异步函数总是返回一个 Promise,即使没有明确地返回一个 Promise,也会隐式地将其返回值包装在一个 resolved Promise 中。
    • 如果异步函数返回了一个非 Promise 值,它会被转换为 resolved Promise,返回值作为 resolve 的参数。
  2. await 关键字:

    • await 关键字只能在 async 函数内部使用。
    • await 后跟一个表达式,这个表达式的值通常是一个 Promise。
    • 当遇到 await 表达式时,JavaScript 会暂停异步函数的执行,等待 Promise 解决(resolved)或拒绝(rejected),然后恢复执行并返回 Promise 的结果或抛出错误。

二、应用场景

  • 当需要串行处理多个异步操作时,async/await 可以帮助消除回调地狱(callback hell)和链式 .then() 方法带来的嵌套层次过深的问题。
  • 在 Node.js 中,用于处理文件 I/O、数据库查询、网络请求等异步操作,使得代码逻辑更加清晰、易于维护。

三、示例代码

// 异步获取数据的模拟函数
function getDataFromApi(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.5) {
        resolve(`Data from ${url}`);
      } else {
        reject(new Error('Failed to fetch data'));
      }
    }, 1000); // 模拟异步延迟
  });
}

// 使用 async/await 的异步函数
async function fetchDataSequentially(urls) {
  let results = [];
  
  for (const url of urls) {
    try {
      const data = await getDataFromApi(url);
      results.push(data);
    } catch (error) {
      console.error(`Error fetching data from ${url}:`, error);
    }
  }

  return results;
}

// 使用示例
(async () => {
  const urls = ['api1', 'api2', 'api3'];
  try {
    const fetchedData = await fetchDataSequentially(urls);
    console.log(fetchedData);
  } catch (error) {
    console.error('An error occurred:', error);
  }
})();

在上面的示例中,fetchDataSequentially 是一个异步函数,它逐个等待 getDataFromApi 的 Promise 完成,并将结果收集到数组 results 中。整个过程无需回调函数或 .then() 链式调用,代码如同同步执行般直观。注意,为了能够启动这个异步操作,我们在全局作用域使用了立即执行的 async 函数表达式 ((async () => {...})() )。

四、注意事项:

使用 async/await 时,需要注意以下几点:

  1. 函数必须带有 async 关键字:

    • 若要在函数内部使用 await 关键字,该函数必须被声明为 async 函数。否则会引发语法错误。
  2. await 后接 Promise:

    • await 关键字后面通常跟着一个返回 Promise 的表达式。如果不是 Promise,它会被转换为已解决(resolved)的 Promise。
    • 如果 await 后的 Promise 被拒绝(rejected),那么 await 表达式将会抛出错误,需要用 try...catch 语句捕获。
  3. 同步外观下的异步行为:

    • 尽管 async/await 提供了类似于同步代码的写法,但实际上它仍然执行的是异步操作。这意味着 await 之后的代码并不会阻塞执行流,而是等待 Promise 解决后才会继续执行。
    • 因此,在某些情况下,需要特别注意代码执行的顺序,特别是涉及多个异步操作时,避免误认为所有操作会按顺序立即执行。
  4. 错误处理:

    • 使用 async/await 编写异步代码时,应该适当地使用 try...catch 结构来捕获和处理可能出现的错误。如果不这样做,Promise 的 rejection 将会导致异常冒泡至外层的 async 函数,并且如果没有被捕获,会导致整个脚本终止。
  5. 并发 vs. 串行:

    • 在循环中使用 await 时,代码默认会按照顺序逐个等待异步操作完成,即串行执行。如果需要并发执行多个异步任务,可以利用 Promise.all 或者 for...of 结合 await 实现。
  6. 资源管理:

    • 在执行一系列异步操作时,尤其涉及数据库连接、文件流或者其他需要释放的资源,要注意及时关闭或释放资源,确保资源在使用完毕后得到妥善处理。
  7. 避免阻塞:

    • 尽管 async/await 使得代码看上去像是同步的,但应当避免在长时间运行的操作前后不加区分地使用 await,以免阻塞事件循环,影响应用的响应性。
  8. 内存占用和性能考量:

    • 如果大量的异步操作堆积在一起,可能会增加内存消耗,因为每一个 async 函数都会生成一个微型任务,加入到任务队列中。在高负载的情况下,需要合理设计异步流程以降低内存压力。
  9. 跨函数传播:

    • 由于 async 函数始终返回一个 Promise,因此在跨函数调用时,需确保下游函数也能正确处理 Promise,或者也将下游函数声明为 async 函数以便使用 await
  10. 兼容性和迁移成本:

    • 虽然现代浏览器和 Node.js 已经全面支持 async/await,但在旧版本环境中可能需要 Babel 等转译工具来确保兼容性。在已有项目中引入 async/await 可能涉及到大量既有代码的重构。
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还是大剑师兰特

打赏一杯可口可乐

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值