JavaScript Promise 与 async/await 实战5 个高频异步编程场景的优雅解决方案在前端开发中异步编程是绕不开的核心技能。从早期的回调函数到 Promise再到如今的 async/awaitJavaScript 的异步处理方式不断进化。本文将通过 5 个实际开发中的高频场景带你掌握 Promise 与 async/await 的优雅用法。场景一串行执行多个异步任务需求按顺序执行多个接口请求后一个请求依赖前一个请求的结果。错误写法回调地狱getUserData(userId, function(user) {getOrders(user.id, function(orders) {getOrderDetails(orders[0].id, function(details) {console.log(details);});});});优雅写法async/awaitasync function fetchOrderDetails(userId) {try {const user await getUserData(userId);const orders await getOrders(user.id);const details await getOrderDetails(orders[0].id);return details;} catch (error) {console.error(获取订单详情失败:, error);throw error;}}关键点await 让异步代码看起来像同步代码逻辑清晰错误处理统一。场景二并行执行多个独立异步任务需求同时发起多个互不依赖的请求等待所有请求完成后统一处理。错误写法串行执行效率低async function fetchAllData() {const user await getUserData();const orders await getOrders();const products await getProducts();return { user, orders, products };}优雅写法Promise.all 并行执行async function fetchAllData() {try {const [user, orders, products] await Promise.all([getUserData(),getOrders(),getProducts()]);return { user, orders, products };} catch (error) {console.error(批量获取数据失败:, error);throw error;}}性能对比假设每个请求耗时 100ms串行需要 300ms并行只需 100ms。进阶技巧处理部分失败的情况async function fetchAllDataWithFallback() {const results await Promise.allSettled([getUserData(),getOrders(),getProducts()]);const user results[0].status fulfilled ? results[0].value : null;const orders results[1].status fulfilled ? results[1].value : [];const products results[2].status fulfilled ? results[2].value : [];return { user, orders, products };}场景三异步请求超时控制需求防止接口响应过慢导致页面卡死设置超时自动取消。优雅写法Promise.race 实现超时function fetchWithTimeout(url, timeout 5000) {const timeoutPromise new Promise((_, reject) {setTimeout(() reject(new Error(请求超时)), timeout);});return Promise.race([fetch(url),timeoutPromise]);}async function fetchDataWithTimeout(url) {try {const response await fetchWithTimeout(url, 5000);const data await response.json();return data;} catch (error) {if (error.message 请求超时) {console.warn(请求超时已自动取消);// 可以显示友好的超时提示}throw error;}}场景四异步重试机制需求网络不稳定时自动重试提高请求成功率。优雅写法指数退避重试async function fetchWithRetry(url, options {}) {const {maxRetries 3,baseDelay 1000,timeout 5000} options;for (let attempt 1; attempt maxRetries; attempt) {try {const response await fetchWithTimeout(url, timeout);if (!response.ok) {throw new Error(HTTP ${response.status});}return await response.json();} catch (error) {if (attempt maxRetries) {console.error(请求失败已重试${maxRetries}次:, error);throw error;}// 指数退避1s, 2s, 4s...const delay baseDelay * Math.pow(2, attempt - 1);console.log(第${attempt}次失败${delay}ms 后重试...);await new Promise(resolve setTimeout(resolve, delay));}}}使用示例const data await fetchWithRetry(/api/user/profile, {maxRetries: 3,baseDelay: 1000,timeout: 5000});场景五请求取消AbortController需求用户快速切换页面时取消未完成的请求避免内存泄漏和数据错乱。优雅写法AbortController 取消请求function createCancelableFetch() {const controller new AbortController();const fetchCancelable async (url) {const response await fetch(url, {signal: controller.signal});return await response.json();};const cancel () {controller.abort();};return { fetchCancelable, cancel };}实际应用React 组件中useEffect(() {const { fetchCancelable, cancel } createCancelableFetch();async function loadData() {try {const data await fetchCancelable(/api/data);setData(data);} catch (error) {if (error.name ! AbortError) {console.error(加载失败:, error);}}}loadData();// 组件卸载或依赖变化时取消请求return () cancel();}, [userId]);综合实战封装通用请求函数将以上技巧整合封装一个生产级别的请求函数async function request(url, options {}) {const {method GET,data null,timeout 5000,maxRetries 3,needAuth true} options;// 添加认证头const headers {Content-Type: application/json,...options.headers};if (needAuth) {const token localStorage.getItem(token);if (token) {headers[Authorization] Bearer ${token};}}// 重试逻辑for (let attempt 1; attempt maxRetries; attempt) {try {const controller new AbortController();const timeoutId setTimeout(() controller.abort(), timeout);const response await fetch(url, {method,headers,body: data ? JSON.stringify(data) : null,signal: controller.signal});clearTimeout(timeoutId);if (!response.ok) {if (response.status 401) {// 未授权跳转登录window.location.href /login;throw new Error(未授权);}throw new Error(HTTP ${response.status});}return await response.json();} catch (error) {if (error.name AbortError) {console.warn(请求已取消);throw error;}if (attempt maxRetries) {console.error(请求失败:, error);throw error;}const delay 1000 * Math.pow(2, attempt - 1);await new Promise(resolve setTimeout(resolve, delay));}}}使用示例const userData await request(/api/user/profile);const orders await request(/api/orders, {method: POST,data: { productId: 123, quantity: 2 }});总结1. 串行依赖用 await清晰直观2. 并行独立用 Promise.all效率翻倍3. 超时控制用 Promise.race防止卡死4. 网络不稳用指数退避重试提高成功率5. 页面切换用 AbortController避免泄漏掌握这 5 个场景你的异步代码将更加优雅、健壮、易维护。异步编程不再可怕而是成为你的得力武器。完