您的位置:首页 > 健康 > 养生 > 网页制作的代码_百度seo排名点击_推广产品引流的最佳方法_百度应用

网页制作的代码_百度seo排名点击_推广产品引流的最佳方法_百度应用

2025/4/3 11:25:46 来源:https://blog.csdn.net/2302_79730293/article/details/146776958  浏览:    关键词:网页制作的代码_百度seo排名点击_推广产品引流的最佳方法_百度应用
网页制作的代码_百度seo排名点击_推广产品引流的最佳方法_百度应用

TypeScript 中 await 的详解

  • 1. 基本概念
  • 2. 语法要求
  • 3. 工作原理
  • 4. 与 Promise 的比较
  • 5. 实践中的注意事项
  • 总结

本文详细介绍了 TypeScript 中 await 的工作原理、语法要求、与 Promise 的关系以及实践中需要注意的问题,同时针对代码示例进行了优化和补充说明。


1. 基本概念

  • 异步编程背景
    传统异步编程常采用回调函数或 Promise 链式调用,这容易导致“回调地狱”(即指的是在处理异步操作时,由于多个回调函数层层嵌套,导致代码结构混乱、可读性差、难以维护和调试的现象)。async/await 提供了类似同步代码的写法,使逻辑更清晰,便于调试和错误处理。

  • await 的作用

    • await 用于等待一个 Promise 的解析结果。当执行到 await 表达式时,当前的 async 函数暂停执行,直到等待的 Promise 进入 成功(resolve)拒绝(reject) 状态,然后继续执行后续代码。
    • 此外,async 函数会自动捕获同步错误,将其转换为返回 Promise 的拒绝状态。
  • async 函数返回值及状态变化

    • async 函数总是返回一个 Promise:

      • 如果函数返回一个非 Promise 值,会等同于返回 Promise.resolve(值)
      • 如果函数内部抛出异常(无论同步或异步错误),返回的 Promise 则进入拒绝状态(reject),异常作为拒绝原因。
    • 示例:

    async function getNumber() {return 42; // 等同于 return Promise.resolve(42)
    }async function throwError() {throw new Error("失败"); // 返回被拒绝的 Promise,状态为 reject
    }
    

2. 语法要求

  • 使用限制
    await 只能在标记为 async 的函数内部使用,否则会导致语法错误。例如:

    async function getData() {const response = await fetch("https://api.example.com/data");return response.json();
    }
    
  • 对非 Promise 值的处理
    如果 await 后面的表达式不是一个 Promise,执行时会直接返回该值(等同于 await Promise.resolve(值))。例如:

    async function testNonPromise() {const result = await 42; // 直接返回 42,等同于 await Promise.resolve(42)console.log(result); // 输出 42
    }
    testNonPromise();
    
  • 对 thenable 对象的处理
    如果表达式是一个具有 then 方法的对象,则会按照 Promise 的规则处理。


3. 工作原理

  • 暂停与状态机
    当遇到 await 表达式时,当前 async 函数会暂停执行,其内部状态被保存。等待 Promise 解析后,会恢复执行。在编译为 ES5 等低版本目标时,TypeScript 会生成类似生成器函数的状态机代码,通常借助 __awaiter 辅助函数实现。

  • 非阻塞主线程
    尽管 async 函数内部暂停执行,但这不会阻塞 JavaScript 的事件循环,主线程仍可响应其他任务。

  • 错误处理
    错误处理方式有两种:

    • try/catch 捕获
      可集中处理多个 await 操作中的错误,适用于同步与异步错误均可捕获。

      async function fetchData() {try {const response = await fetch("https://api.example.com/data");if (!response.ok) throw new Error("请求失败");const data = await response.json();console.log(data);} catch (error) {console.error("获取数据失败:", error);}
      }
      

      说明:try/catch 块不仅能捕获 await 等待期间的异步错误,还能捕获函数内部抛出的同步错误。

    • 使用 .catch() 方法
      可在单个 Promise 后直接捕获错误,并返回默认值以便后续流程继续。

      async function fetchDataWithCatch() {const response = await fetch("https://api.example.com/data").catch(error => {console.error("获取数据失败:", error);return null;});if (response) {if (!response.ok) throw new Error("请求失败");const data = await response.json();console.log(data);}
      }
      

4. 与 Promise 的比较

  • 可读性提升
    使用 async/await 使得代码逻辑看起来更接近同步流程,避免了大量 .then() 的嵌套,使错误处理更为集中。

  • 编译转换细节
    TypeScript 编译器会将 async/await 转换为基于 Promise 的实现。在目标环境为 ES5 或 ES6 时,转换后的代码可能会借助 __awaiter 辅助函数或生成器函数实现状态机逻辑。例如:

    async function fetchData() {const result = await fetch("https://api.example.com/data");if (!result.ok) throw new Error("请求失败");return await result.json();
    }
    

    转换后相当于:

    function fetchData() {return __awaiter(this, void 0, void 0, function* () {const result = yield fetch("https://api.example.com/data");if (!result.ok) throw new Error("请求失败");return yield result.json();});
    }
    

    说明:这里展示的转换逻辑只是示例,具体实现依赖 TypeScript 版本和目标运行环境。


5. 实践中的注意事项

  • 错误处理策略
    对每个 await 操作都建议采用 try/catch 或在调用处使用 .catch() 来捕获错误,确保程序健壮性。
    例如:

    async function riskyOperation() {const response = await fetch("https://api.example.com/data");if (!response.ok) throw new Error("请求失败");return response.json();
    }riskyOperation().catch(error => {console.error("外部捕获错误:", error);
    });
    
  • 并行与串行操作
    对于多个互不依赖的异步操作,若依次使用 await 会导致串行执行,从而影响性能。建议使用 Promise.all 并行处理:

    async function fetchMultipleData() {const [data1, data2] = await Promise.all([fetch("https://api.example.com/data1").then(res => {if (!res.ok) throw new Error("data1 请求失败");return res.json();}),fetch("https://api.example.com/data2").then(res => {if (!res.ok) throw new Error("data2 请求失败");return res.json();})]);console.log(data1, data2);
    }
    

    若希望即使部分操作失败也能获得全部结果,则可使用 Promise.allSettled

    async function fetchMultipleDataWithAllSettled() {const results = await Promise.allSettled([fetch("https://api.example.com/data1").then(res => res.json()),fetch("https://api.example.com/data2").then(res => res.json())]);results.forEach(result => {if (result.status === 'fulfilled') {console.log(result.value);} else {console.error("失败原因:", result.reason);}});
    }
    

    说明:在 Promise.allSettled 的示例中,result.reason 类型为 any,视情况可进行类型断言处理。

  • 其他实践建议

    • HTTP 状态码检查:建议对 fetch 返回的响应进行 response.ok 检查,以确保请求成功
    • 循环中的 await:当需要对异步迭代(如读取流、异步生成器)时,可使用 for-await-of 循环
    • top-level await:在模块环境下(ESM 模块)TypeScript 也支持顶层 await,但需要确保目标环境的兼容性
    • 术语统一:文中统一使用“拒绝(reject)”描述 Promise 的拒绝状态

总结

通过使用 async/await,我们可以编写出逻辑清晰、易于调试和维护的异步代码。关键要点包括:

  • await 只能在 async 函数内使用;
  • async 函数返回 Promise,内部的同步错误会转换为 Promise 的拒绝状态;
  • 合理使用 try/catch 和 .catch() 进行错误处理;
  • 对于多个互不依赖的异步操作,建议采用并行执行方式(如 Promise.allPromise.allSettled)以提升性能;
  • 需注意 HTTP 响应状态码、循环中的异步处理以及 top-level await 的环境要求。

同时需要认识到,async/await 并非完全替代 Promise,而是对其进行封装和补充,使得异步代码在语义和结构上更加直观。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com