[JS Daily] Promise 与 async/await:异步编程的优雅解法 #JavaScript #ES6 #异步编程 #教程
- 获取链接
- X
- 电子邮件
- 其他应用
⚡
JavaScript 每日一题
Promise 与 async/await:异步编程的优雅解法
#JavaScript #ES6 #异步编程 #教程
📋 本节要点
- 理解 JavaScript 异步编程的本质与事件循环
- 掌握 Promise 的三种状态与链式调用
- 学会 async/await 语法糖的正确使用
- 处理异步错误与并行任务的优化策略
一、为什么需要异步?
JavaScript 是单线程语言,这意味着同一时间只能执行一个任务。如果所有操作都是同步的,那么网络请求、文件读取、定时器等耗时操作会阻塞整个程序,导致页面卡死。
异步编程的核心思想是:把耗时任务交给其他模块处理,主线程继续执行后续代码。当任务完成时,通过回调、Promise 或 async/await 来处理结果。
💡 事件循环(Event Loop)
JavaScript 引擎通过事件循环机制管理异步任务。调用栈执行同步代码,任务队列排队异步回调。当调用栈空闲时,事件循环从任务队列取出回调执行。
二、Promise:异步的承诺
Promise 是 ES6 引入的异步解决方案,它代表一个未来才会知道结果的操作。Promise 有三种状态:
⏳
Pending
进行中
✅
Fulfilled
已成功
❌
Rejected
已失败
2.1 创建 Promise
const fetchData = new Promise((resolve, reject) => { const success = true; setTimeout(() => { if (success) { resolve({ data: 'Hello Promise' }); } else { reject(new Error('请求失败')); } }, 1000); }); 2.2 链式调用
Promise 的强大之处在于链式调用,避免回调地狱:
fetchData .then(result => { console.log(result.data); // 'Hello Promise' return result.data.toUpperCase(); }) .then(upper => { console.log(upper); // 'HELLO PROMISE' }) .catch(error => { console.error(error.message); }) .finally(() => { console.log('请求结束'); }); 三、async/await:同步的写法
ES2017 引入的 async/await 是 Promise 的语法糖,让异步代码写起来像同步代码一样清晰。
3.1 基本语法
async function getData() { try { const result = await fetchData; console.log(result.data); } catch (error) { console.error(error.message); } } getData(); 📌 核心规则
async函数返回值自动包装成 Promiseawait只能在async函数内使用await后面跟 Promise,如果不是会自动转成 resolved Promise
3.2 并行处理
当多个异步操作相互独立时,使用 Promise.all() 并行执行:
async function fetchAll() { const [users, posts, comments] = await Promise.all([ fetch('/api/users'), fetch('/api/posts'), fetch('/api/comments') ]); return { users, posts, comments }; } 四、错误处理的最佳实践
async function safeRequest(url) { try { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return await response.json(); } catch (error) { // 记录日志 console.error(`请求失败: ${url}`, error); // 返回默认值或重新抛出 throw error; // 或 return null; } } 五、Promise vs async/await 对比
| 特性 | Promise | async/await |
|---|---|---|
| 可读性 | 链式调用,中等 | 同步写法,最佳 |
| 错误处理 | .catch() 统一处理 | try/catch 同步风格 |
| 调试体验 | 断点不明显 | 断点直观清晰 |
| 并行处理 | Promise.all() 原生支持 | 需要配合 Promise.all() |
| 兼容性 | ES6,广泛支持 | ES2017,需转译 |
六、实战案例:API 请求封装
// 封装带重试的请求函数 async function requestWithRetry(url, options = {}, retries = 3) { for (let i = 0; i < retries; i++) { try { const response = await fetch(url, options); if (!response.ok) throw new Error(`HTTP ${response.status}`); return await response.json(); } catch (error) { if (i === retries - 1) throw error; console.log(`重试 ${i + 1}/${retries}`); await new Promise(r => setTimeout(r, 1000 * (i + 1))); } } } // 使用示例 async function loadUserData() { try { const data = await requestWithRetry('/api/user'); console.log('用户数据:', data); } catch (error) { console.error('最终失败:', error); } } 🎯 本节小结
- Promise 是异步编程的基础,理解三种状态至关重要
- async/await 让异步代码更易读、更易调试
- 并行任务用
Promise.all(),错误处理用 try/catch - 实际项目中推荐封装统一的请求函数
📝 课后练习
- 手写一个
Promise.race()的实现 - 将回调风格的
setTimeout封装成 Promise - 实现一个并发控制的请求函数(最多同时 N 个请求)
🦐 虾米团队 · JavaScript 每日一题系列
2026-03-18 · 第三期 · Promise 与 async/await
- 获取链接
- X
- 电子邮件
- 其他应用
评论
发表评论