异步编程核心概念
1. 为什么需要异步?
避免阻塞:JavaScript是单线程语言,异步操作可防止长时间任务阻塞主线程
提升性能:充分利用I/O等待时间处理其他任务
响应式体验:保持UI流畅响应,特别是在浏览器环境中
2. 事件循环机制
// 演示事件循环执行顺序console.log('Start');setTimeout(() => console.log('Timeout'), 0);Promise.resolve().then(() => console.log('Promise'));console.log('End');/* 输出顺序:StartEndPromiseTimeout*/
3. 执行上下文
调用栈(Call Stack):同步代码执行容器
任务队列(Task Queue):存放宏任务(setTimeout、I/O)
微任务队列(Microtask Queue):存放微任务(Promise、MutationObserver)
异步编程演进史
1. 回调函数(Callback)
function fetchData(callback) {setTimeout(() => {callback('Data received');}, 1000);}fetchData((data) => {console.log(data); // 1秒后输出});
回调函数存在的问题:回调地狱(Callback Hell)
-
getUser(userId, (user) => {getOrders(user.id, (orders) => {getProducts(orders[0].id, (products) => {renderPage(user, orders, products);});});});2. Promise(ES6)
const promiseExample = new Promise((resolve, reject) => {setTimeout(() => {Math.random() > 0.5 ?resolve('Success!') :reject(new Error('Failed'));}, 1000);});promiseExample.then(console.log).catch(console.error);3. async/await(ES2017)
async function fetchUser() {try {const response = await fetch('/api/user');const data = await response.json();return data;} catch (error) {console.error('Fetch failed:', error);}}
Promise 深度解析
1. 状态管理
Pending(进行中)
Fulfilled(已成功)
Rejected(已失败)
2. 链式调用
checkInventory().then((stock) => placeOrder(stock)).then((order) => processPayment(order)).then((receipt) => sendConfirmation(receipt)).catch(handleErrors);
3. 组合方法
// 并行执行Promise.all([api1, api2, api3]).then(([res1, res2, res3]) => { /* ... */ });// 竞速模式Promise.race([fastAPI, slowAPI]).then(firstResult => { /* ... */ });// 全成功或全部失败Promise.allSettled([req1, req2]).then(results => { /* ... */ });
async/await最佳实践
1. 错误处理模式
// 方法1:try/catchasync function safeFetch() {try {const res = await fetch(url);return await res.json();} catch (err) {console.error('Request failed:', err);return null;}}// 方法2:高阶函数封装const asyncHandler = (promise) =>promise.then(data => [null, data]).catch(err => [err, null]);
2. 并行优化
// 顺序执行(低效)const user = await getUser();const orders = await getOrders(user.id);// 并行执行(推荐)const [user, orders] = await Promise.all([getUser(),getOrders(userId)]);
3. 循环中的异步
// 错误方式(forEach不等待)array.forEach(async item => {await process(item);});// 正确方式for (const item of array) {await process(item); // 顺序执行}// 并行方式await Promise.all(array.map(item => process(item)));
高级异步模式
1. 发布订阅模式
class EventEmitter {constructor() {this.events = {};}on(event, listener) {(this.events[event] || (this.events[event] = [])).push(listener);}emit(event, ...args) {(this.events[event] || []).forEach(listener => listener(...args));}}
2. 数据流处理(RxJS示例)
import { fromEvent } from 'rxjs';import { debounceTime, map } from 'rxjs/operators';const searchInput = document.getElementById('search');fromEvent(searchInput, 'input').pipe(debounceTime(300),map(e => e.target.value)).subscribe(value => {// 执行搜索});
3. Web Workers
// main.jsconst worker = new Worker('worker.js');worker.postMessage({ type: 'CALC', data: bigArray });worker.onmessage = (e) => {console.log('Result:', e.data);};// worker.jsself.onmessage = function(e) {if (e.data.type === 'CALC') {const result = heavyCalculation(e.data.data);self.postMessage(result);}};
错误处理策略
1. 全局错误捕获
// 浏览器环境window.addEventListener('unhandledrejection', (event) => {console.error('Unhandled rejection:', event.reason);});// Node.js环境process.on('unhandledRejection', (reason, promise) => {console.error('Unhandled Rejection at:', promise, 'reason:', reason);});
2. 重试机制
async function retry(fn, retries = 3, delay = 1000) {try {return await fn();} catch (err) {if (retries <= 0) throw err;await new Promise(res => setTimeout(res, delay));return retry(fn, retries - 1, delay * 2);}}
性能优化技巧
1. 节流防抖
// 防抖实现function debounce(fn, delay) {let timer;return (...args) => {clearTimeout(timer);timer = setTimeout(() => fn(...args), delay);};}// 节流实现function throttle(fn, interval) {let lastTime = 0;return (...args) => {const now = Date.now();if (now - lastTime >= interval) {fn(...args);lastTime = now;}};}
2. 请求缓存
const apiCache = new Map();async function cachedFetch(url) {if (apiCache.has(url)) {return apiCache.get(url);}const response = await fetch(url);const data = await response.json();apiCache.set(url, data);return data;}
实际开发应用场景
1. AJAX请求处理
async function loadPageData() {const [user, posts] = await Promise.all([fetch('/api/user'),fetch('/api/posts')]);return {user: await user.json(),posts: await posts.json()};}
2. 文件上传处理
async function uploadFiles(files) {const uploadPromises = files.map(file => {const formData = new FormData();formData.append('file', file);return fetch('/upload', {method: 'POST',body: formData});});const results = await Promise.allSettled(uploadPromises);// 处理上传结果}
总结
1.优先使用async/await:提升代码可读性
2. 避免过度并行:控制并发数量(使用p-limit等库)
3.及时清理资源:取消不必要的请求(AbortController)
4.监控异步性能:使用Performance API进行分析
5.保持错误可追踪:附加上下文错误信息
// 使用AbortController取消请求const controller = new AbortController();fetch(url, { signal: controller.signal }).then(/* ... */).catch(err => {if (err.name === 'AbortError') {console.log('Request aborted');}});// 取消请求controller.abort();
![]() |
Austin Liu 刘恒辉
Project Manager and Software Designer E-Mail:lzhdim@163.com Blog:https://lzhdim.cnblogs.com 欢迎收藏和转载此博客中的博文,但是请注明出处,给笔者一个与大家交流的空间。谢谢大家。 |




浙公网安备 33010602011771号