异步编程概述
什么是异步编程
异步编程是一种编程范式,允许程序在等待某些操作完成时继续执行其他任务,而不是阻塞整个程序的执行。在JavaScript中,异步编程是处理网络请求、文件操作、定时器等耗时操作的核心机制。
// 同步代码示例
console.log('开始');
console.log('中间');
console.log('结束');
// 输出顺序:开始 -> 中间 -> 结束
// 异步代码示例
console.log('开始');
setTimeout(() => {
console.log('异步操作完成');
}, 1000);
console.log('结束');
// 输出顺序:开始 -> 结束 -> 异步操作完成(1秒后)
JavaScript的事件循环
理解事件循环是掌握异步编程的关键:
// 事件循环示例
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// 输出顺序:1 -> 4 -> 3 -> 2
// 解释:
// 1. 同步代码先执行:1, 4
// 2. 微任务队列(Promise)优先于宏任务队列(setTimeout):3
// 3. 最后执行宏任务:2
异步编程的发展历程
// 1. 回调函数时代
function fetchData(callback) {
setTimeout(() => {
callback(null, 'data');
}, 1000);
}
// 2. Promise时代
function fetchDataPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('data');
}, 1000);
});
}
// 3. async/await时代
async function fetchDataAsync() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('data');
}, 1000);
});
}
回调函数
基本回调函数
// 简单回调函数
function greet(name, callback) {
console.log(`Hello, ${name}!`);
callback();
}
function afterGreeting() {
console.log('Nice to meet you!');
}
greet('Alice', afterGreeting);
// 输出:
// Hello, Alice!
// Nice to meet you!
// 匿名回调函数
greet('Bob', function() {
console.log('How are you?');
});
// 箭头函数回调
greet('Charlie', () => {
console.log('See you later!');
});
异步回调函数
// 模拟异步操作
function simulateAsyncOperation(data, callback) {
console.log('开始异步操作...');
setTimeout(() => {
const result = data.toUpperCase();
callback(null, result); // 第一个参数是错误,第二个是结果
}, 1000);
}
// 使用异步回调
simulateAsyncOperation('hello world', (error, result) => {
if (error) {
console.error('操作失败:', error);
} else {
console.log('操作成功:', result);
}
});
// 错误处理示例
function riskyOperation(shouldFail, callback) {
setTimeout(() => {
if (shouldFail) {
callback(new Error('操作失败'), null);
} else {
callback(null, '操作成功');
}
}, 500);
}
riskyOperation(true, (error, result) => {
if (error) {
console.error('错误:', error.message);
} else {
console.log('结果:', result);
}
});
回调地狱问题
// 回调地狱示例
function step1(callback) {
setTimeout(() => {
console.log('Step 1 完成');
callback(null, 'result1');
}, 1000);
}
function step2(data, callback) {
setTimeout(() => {
console.log('Step 2 完成,接收到:', data);
callback(null, 'result2');
}, 1000);
}
function step3(data, callback) {
setTimeout(() => {
console.log('Step 3 完成,接收到:', data);
callback(null, 'final result');
}, 1000);
}
// 嵌套回调(回调地狱)
step1((err1, result1) => {
if (err1) {
console.error('Step 1 失败:', err1);
return;
}
step2(result1, (err2, result2) => {
if (err2) {
console.error('Step 2 失败:', err2);
return;
}
step3(result2, (err3, result3) => {
if (err3) {
console.error('Step 3 失败:', err3);
return;
}
console.log('最终结果:', result3);
});
});
});
// 改进:使用命名函数减少嵌套
function handleStep1(err1, result1) {
if (err1) {
console.error('Step 1 失败:', err1);
return;
}
step2(result1, handleStep2);
}
function handleStep2(err2, result2) {
if (err2) {
console.error('Step 2 失败:', err2);
return;
}
step3(result2, handleStep3);
}
function handleStep3(err3, result3) {
if (err3) {
console.error('Step 3 失败:', err3);
return;
}
console.log('最终结果:', result3);
}
step1(handleStep1);
Promise基础
Promise的创建和基本用法
// 创建Promise
const myPromise = new Promise((resolve, reject) => {
// 异步操作
const success = Math.random() > 0.5;
setTimeout(() => {
if (success) {
resolve('操作成功!');
} else {
reject(new Error('操作失败!'));
}
}, 1000);
});
// 使用Promise
myPromise
.then(result => {
console.log('成功:', result);
})
.catch(error => {
console.error('失败:', error.message);
})
.finally(() => {
console.log('操作完成(无论成功或失败)');
});
// Promise的三种状态
function demonstratePromiseStates() {
// 1. Pending(等待中)
const pendingPromise = new Promise((resolve, reject) => {
// 不调用resolve或reject,保持pending状态
});
console.log('Pending Promise:', pendingPromise);
// 2. Fulfilled(已完成)
const fulfilledPromise = Promise.resolve('成功的值');
console.log('Fulfilled Promise:', fulfilledPromise);
// 3. Rejected(已拒绝)
const rejectedPromise = Promise.reject(new Error('失败的原因'));
console.log('Rejected Promise:', rejectedPromise);
// 处理rejected promise以避免未捕获的错误
rejectedPromise.catch(() => {});
}
demonstratePromiseStates();
Promise链式调用
// 基本链式调用
function createPromise(value, delay = 1000) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`处理: ${value}`);
resolve(value);
}, delay);
});
}
// 链式调用示例
createPromise('第一步')
.then(result => {
console.log('第一步完成:', result);
return createPromise('第二步');
})
.then(result => {
console.log('第二步完成:', result);
return createPromise('第三步');
})
.then(result => {
console.log('第三步完成:', result);
return '最终结果';
})
.then(finalResult => {
console.log('所有步骤完成:', finalResult);
})
.catch(error => {
console.error('某个步骤失败:', error);
});
// 数据转换链
Promise.resolve(10)
.then(x => x * 2) // 20
.then(x => x + 5) // 25
.then(x => x.toString()) // "25"
.then(str => str.split('')) // ["2", "5"]
.then(arr => arr.reverse()) // ["5", "2"]
.then(arr => arr.join('-')) // "5-2"
.then(result => {
console.log('转换结果:', result);
});
// 错误传播
Promise.resolve('开始')
.then(value => {
console.log('步骤1:', value);
throw new Error('步骤1出错');
})
.then(value => {
// 这个then不会执行,因为上一步抛出了错误
console.log('步骤2:', value);
return '步骤2完成';
})
.then(value => {
// 这个then也不会执行
console.log('步骤3:', value);
})
.catch(error => {
console.error('捕获错误:', error.message);
return '错误已处理';
})
.then(value => {
// 错误被catch处理后,链式调用继续
console.log('恢复执行:', value);
});
Promise静态方法
// Promise.resolve() 和 Promise.reject()
const resolvedPromise = Promise.resolve('立即解决');
const rejectedPromise = Promise.reject(new Error('立即拒绝'));
resolvedPromise.then(console.log); // "立即解决"
rejectedPromise.catch(console.error); // Error: 立即拒绝
// Promise.all() - 所有Promise都成功才成功
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log('Promise.all 结果:', results); // [1, 2, 3]
})
.catch(error => {
console.error('Promise.all 失败:', error);
});
// Promise.all() 失败示例
const failingPromise = Promise.reject(new Error('失败了'));
Promise.all([promise1, failingPromise, promise3])
.then(results => {
console.log('不会执行到这里');
})
.catch(error => {
console.error('Promise.all 失败:', error.message); // "失败了"
});
// Promise.allSettled() - 等待所有Promise完成(无论成功或失败)
Promise.allSettled([promise1, failingPromise, promise3])
.then(results => {
console.log('Promise.allSettled 结果:', results);
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: Error: 失败了 },
// { status: 'fulfilled', value: 3 }
// ]
});
// Promise.race() - 第一个完成的Promise决定结果
const slowPromise = new Promise(resolve => {
setTimeout(() => resolve('慢的'), 2000);
});
const fastPromise = new Promise(resolve => {
setTimeout(() => resolve('快的'), 1000);
});
Promise.race([slowPromise, fastPromise])
.then(result => {
console.log('Promise.race 结果:', result); // "快的"
});
// Promise.any() - 第一个成功的Promise决定结果
const failPromise1 = Promise.reject(new Error('错误1'));
const failPromise2 = Promise.reject(new Error('错误2'));
const successPromise = new Promise(resolve => {
setTimeout(() => resolve('成功了'), 1500);
});
Promise.any([failPromise1, failPromise2, successPromise])
.then(result => {
console.log('Promise.any 结果:', result); // "成功了"
})
.catch(error => {
console.error('所有Promise都失败了:', error);
});
async/await
基本语法
// 基本async函数
async function simpleAsyncFunction() {
return 'Hello, async!';
}
// async函数总是返回Promise
simpleAsyncFunction().then(console.log); // "Hello, async!"
// 等价的Promise写法
function promiseFunction() {
return Promise.resolve('Hello, Promise!');
}
// 使用await等待Promise
async function waitForPromise() {
const result = await simpleAsyncFunction();
console.log('等待结果:', result);
return result;
}
waitForPromise();
// 模拟异步操作
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demonstrateAwait() {
console.log('开始');
await delay(1000);
console.log('1秒后');
await delay(1000);
console.log('2秒后');
await delay(1000);
console.log('3秒后');
return '完成';
}
demonstrateAwait().then(console.log);
错误处理
// 使用try-catch处理错误
async function handleErrors() {
try {
const result = await Promise.reject(new Error('出错了'));
console.log('不会执行到这里');
} catch (error) {
console.error('捕获错误:', error.message);
}
}
handleErrors();
// 多个await的错误处理
async function multipleOperations() {
try {
const result1 = await Promise.resolve('第一个操作成功');
console.log(result1);
const result2 = await Promise.reject(new Error('第二个操作失败'));
console.log('不会执行到这里');
const result3 = await Promise.resolve('第三个操作');
console.log('也不会执行到这里');
} catch (error) {
console.error('操作失败:', error.message);
} finally {
console.log('清理工作');
}
}
multipleOperations();
// 分别处理每个操作的错误
async function handleEachError() {
let result1, result2, result3;
try {
result1 = await Promise.resolve('第一个操作成功');
console.log(result1);
} catch (error) {
console.error('第一个操作失败:', error.message);
}
try {
result2 = await Promise.reject(new Error('第二个操作失败'));
console.log(result2);
} catch (error) {
console.error('第二个操作失败:', error.message);
result2 = '默认值';
}
try {
result3 = await Promise.resolve('第三个操作成功');
console.log(result3);
} catch (error) {
console.error('第三个操作失败:', error.message);
}
return { result1, result2, result3 };
}
handleEachError().then(console.log);
并发执行
// 串行执行(一个接一个)
async function serialExecution() {
console.time('串行执行');
const result1 = await delay(1000).then(() => '任务1完成');
const result2 = await delay(1000).then(() => '任务2完成');
const result3 = await delay(1000).then(() => '任务3完成');
console.timeEnd('串行执行'); // 约3秒
return [result1, result2, result3];
}
// 并行执行(同时开始)
async function parallelExecution() {
console.time('并行执行');
const promise1 = delay(1000).then(() => '任务1完成');
const promise2 = delay(1000).then(() => '任务2完成');
const promise3 = delay(1000).then(() => '任务3完成');
const results = await Promise.all([promise1, promise2, promise3]);
console.timeEnd('并行执行'); // 约1秒
return results;
}
// 使用Promise.all的async/await版本
async function parallelWithPromiseAll() {
console.time('Promise.all并行');
const results = await Promise.all([
delay(1000).then(() => '任务1完成'),
delay(1000).then(() => '任务2完成'),
delay(1000).then(() => '任务3完成')
]);
console.timeEnd('Promise.all并行'); // 约1秒
return results;
}
// 测试执行时间
async function compareExecutionTimes() {
await serialExecution();
await parallelExecution();
await parallelWithPromiseAll();
}
compareExecutionTimes();
// 限制并发数量
async function limitedConcurrency(tasks, limit) {
const results = [];
for (let i = 0; i < tasks.length; i += limit) {
const batch = tasks.slice(i, i + limit);
const batchResults = await Promise.all(
batch.map(task => task())
);
results.push(...batchResults);
}
return results;
}
// 使用限制并发
const tasks = Array.from({ length: 10 }, (_, i) =>
() => delay(1000).then(() => `任务${i + 1}完成`)
);
limitedConcurrency(tasks, 3).then(results => {
console.log('限制并发结果:', results);
});
实际应用示例
网络请求封装
// 基础HTTP客户端
class HttpClient {
constructor(baseURL = '') {
this.baseURL = baseURL;
this.defaultHeaders = {
'Content-Type': 'application/json'
};
}
async request(url, options = {}) {
const fullURL = this.baseURL + url;
const config = {
headers: { ...this.defaultHeaders, ...options.headers },
...options
};
try {
const response = await fetch(fullURL, config);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return await response.json();
}
return await response.text();
} catch (error) {
console.error('请求失败:', error);
throw error;
}
}
async get(url, headers = {}) {
return this.request(url, { method: 'GET', headers });
}
async post(url, data, headers = {}) {
return this.request(url, {
method: 'POST',
headers,
body: JSON.stringify(data)
});
}
async put(url, data, headers = {}) {
return this.request(url, {
method: 'PUT',
headers,
body: JSON.stringify(data)
});
}
async delete(url, headers = {}) {
return this.request(url, { method: 'DELETE', headers });
}
}
// 使用HTTP客户端
const api = new HttpClient('https://jsonplaceholder.typicode.com');
async function demonstrateHttpClient() {
try {
// GET请求
const posts = await api.get('/posts');
console.log('获取文章:', posts.slice(0, 3));
// POST请求
const newPost = await api.post('/posts', {
title: '新文章',
body: '文章内容',
userId: 1
});
console.log('创建文章:', newPost);
// PUT请求
const updatedPost = await api.put('/posts/1', {
id: 1,
title: '更新的文章',
body: '更新的内容',
userId: 1
});
console.log('更新文章:', updatedPost);
// DELETE请求
await api.delete('/posts/1');
console.log('删除文章成功');
} catch (error) {
console.error('API调用失败:', error.message);
}
}
// demonstrateHttpClient();
数据加载器
// 数据加载器类
class DataLoader {
constructor() {
this.cache = new Map();
this.loading = new Map();
}
async load(key, fetcher, options = {}) {
const { useCache = true, timeout = 5000 } = options;
// 检查缓存
if (useCache && this.cache.has(key)) {
console.log(`从缓存加载: ${key}`);
return this.cache.get(key);
}
// 检查是否正在加载
if (this.loading.has(key)) {
console.log(`等待加载完成: ${key}`);
return this.loading.get(key);
}
// 创建加载Promise
const loadingPromise = this.createLoadingPromise(key, fetcher, timeout);
this.loading.set(key, loadingPromise);
try {
const result = await loadingPromise;
// 缓存结果
if (useCache) {
this.cache.set(key, result);
}
return result;
} finally {
// 清理加载状态
this.loading.delete(key);
}
}
async createLoadingPromise(key, fetcher, timeout) {
return Promise.race([
fetcher(key),
new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`加载超时: ${key}`));
}, timeout);
})
]);
}
async loadMultiple(keys, fetcher, options = {}) {
const { concurrency = 3 } = options;
const results = [];
for (let i = 0; i < keys.length; i += concurrency) {
const batch = keys.slice(i, i + concurrency);
const batchPromises = batch.map(key =>
this.load(key, fetcher, options)
);
const batchResults = await Promise.allSettled(batchPromises);
results.push(...batchResults);
}
return results;
}
clearCache(key) {
if (key) {
this.cache.delete(key);
} else {
this.cache.clear();
}
}
getCacheSize() {
return this.cache.size;
}
}
// 模拟数据获取函数
async function fetchUserData(userId) {
console.log(`正在获取用户数据: ${userId}`);
await delay(Math.random() * 2000 + 1000); // 1-3秒随机延迟
if (Math.random() < 0.1) { // 10%的失败率
throw new Error(`获取用户${userId}失败`);
}
return {
id: userId,
name: `用户${userId}`,
email: `user${userId}@example.com`,
createdAt: new Date().toISOString()
};
}
// 使用数据加载器
async function demonstrateDataLoader() {
const loader = new DataLoader();
try {
console.log('=== 单个数据加载 ===');
const user1 = await loader.load('user1', fetchUserData);
console.log('用户1:', user1);
// 再次加载相同数据(应该从缓存获取)
const user1Again = await loader.load('user1', fetchUserData);
console.log('用户1(缓存):', user1Again);
console.log('\n=== 批量数据加载 ===');
const userIds = ['user2', 'user3', 'user4', 'user5', 'user6'];
const results = await loader.loadMultiple(userIds, fetchUserData, {
concurrency: 2,
timeout: 3000
});
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`${userIds[index]}:`, result.value);
} else {
console.error(`${userIds[index]} 失败:`, result.reason.message);
}
});
console.log('\n缓存大小:', loader.getCacheSize());
} catch (error) {
console.error('数据加载失败:', error.message);
}
}
// demonstrateDataLoader();
重试机制
// 重试工具函数
async function retry(fn, options = {}) {
const {
maxAttempts = 3,
delay = 1000,
backoff = 'exponential', // 'fixed', 'exponential', 'linear'
shouldRetry = (error) => true
} = options;
let lastError;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
console.log(`尝试 ${attempt}/${maxAttempts}`);
return await fn();
} catch (error) {
lastError = error;
console.error(`尝试 ${attempt} 失败:`, error.message);
// 检查是否应该重试
if (!shouldRetry(error) || attempt === maxAttempts) {
break;
}
// 计算延迟时间
let waitTime = delay;
switch (backoff) {
case 'exponential':
waitTime = delay * Math.pow(2, attempt - 1);
break;
case 'linear':
waitTime = delay * attempt;
break;
case 'fixed':
default:
waitTime = delay;
break;
}
console.log(`等待 ${waitTime}ms 后重试...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
throw lastError;
}
// 模拟不稳定的网络请求
let attemptCount = 0;
async function unstableNetworkRequest() {
attemptCount++;
if (attemptCount < 3) {
throw new Error(`网络错误 (尝试 ${attemptCount})`);
}
return { data: '请求成功', attempt: attemptCount };
}
// 使用重试机制
async function demonstrateRetry() {
try {
const result = await retry(unstableNetworkRequest, {
maxAttempts: 5,
delay: 500,
backoff: 'exponential',
shouldRetry: (error) => {
// 只对网络错误重试
return error.message.includes('网络错误');
}
});
console.log('最终结果:', result);
} catch (error) {
console.error('重试失败:', error.message);
}
}
// demonstrateRetry();
// 带有断路器模式的重试
class CircuitBreaker {
constructor(options = {}) {
this.failureThreshold = options.failureThreshold || 5;
this.resetTimeout = options.resetTimeout || 60000;
this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
this.failureCount = 0;
this.lastFailureTime = null;
}
async execute(fn) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime >= this.resetTimeout) {
this.state = 'HALF_OPEN';
console.log('断路器状态: HALF_OPEN');
} else {
throw new Error('断路器开启,拒绝请求');
}
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
console.log('断路器状态: CLOSED');
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) {
this.state = 'OPEN';
console.log('断路器状态: OPEN');
}
}
getState() {
return {
state: this.state,
failureCount: this.failureCount,
lastFailureTime: this.lastFailureTime
};
}
}
// 使用断路器
const circuitBreaker = new CircuitBreaker({
failureThreshold: 3,
resetTimeout: 5000
});
async function demonstrateCircuitBreaker() {
for (let i = 0; i < 10; i++) {
try {
await delay(1000);
const result = await circuitBreaker.execute(async () => {
if (Math.random() < 0.7) { // 70%失败率
throw new Error('服务不可用');
}
return '服务正常';
});
console.log(`请求 ${i + 1}: ${result}`);
} catch (error) {
console.error(`请求 ${i + 1} 失败: ${error.message}`);
}
console.log('断路器状态:', circuitBreaker.getState());
}
}
// demonstrateCircuitBreaker();
性能优化和最佳实践
避免常见陷阱
// 1. 避免在循环中使用await(串行执行)
// 错误做法
async function inefficientLoop(urls) {
const results = [];
for (const url of urls) {
const result = await fetch(url); // 串行执行,很慢
results.push(result);
}
return results;
}
// 正确做法
async function efficientLoop(urls) {
const promises = urls.map(url => fetch(url)); // 并行启动
return Promise.all(promises); // 等待所有完成
}
// 2. 正确处理Promise.all的错误
async function handlePromiseAllErrors(tasks) {
try {
const results = await Promise.all(tasks);
return results;
} catch (error) {
console.error('某个任务失败:', error);
// 使用Promise.allSettled获取所有结果
const allResults = await Promise.allSettled(tasks);
return allResults.filter(result => result.status === 'fulfilled')
.map(result => result.value);
}
}
// 3. 避免忘记await
async function forgotAwait() {
// 错误:忘记await
const promise = delay(1000);
console.log('立即执行,不等待');
// 正确:使用await
await delay(1000);
console.log('等待1秒后执行');
}
// 4. 正确使用async/await和Promise.then混合
async function mixingAsyncAwaitAndThen() {
// 不推荐:混合使用
const result1 = await fetch('/api/data')
.then(response => response.json())
.then(data => data.value);
// 推荐:保持一致性
const response = await fetch('/api/data');
const data = await response.json();
const result2 = data.value;
return { result1, result2 };
}
// 5. 内存泄漏预防
class AsyncTaskManager {
constructor() {
this.activeTasks = new Set();
this.cancelled = false;
}
async runTask(taskFn) {
if (this.cancelled) {
throw new Error('任务管理器已取消');
}
const taskPromise = taskFn();
this.activeTasks.add(taskPromise);
try {
const result = await taskPromise;
return result;
} finally {
this.activeTasks.delete(taskPromise);
}
}
async cancelAll() {
this.cancelled = true;
// 等待所有活动任务完成或超时
const timeout = new Promise(resolve => setTimeout(resolve, 5000));
const allTasks = Promise.all(Array.from(this.activeTasks));
await Promise.race([allTasks, timeout]);
this.activeTasks.clear();
}
getActiveTaskCount() {
return this.activeTasks.size;
}
}
性能监控
// 异步操作性能监控
class AsyncPerformanceMonitor {
constructor() {
this.metrics = new Map();
}
async measure(name, asyncFn) {
const startTime = performance.now();
const startMemory = this.getMemoryUsage();
try {
const result = await asyncFn();
this.recordSuccess(name, startTime, startMemory);
return result;
} catch (error) {
this.recordFailure(name, startTime, startMemory, error);
throw error;
}
}
recordSuccess(name, startTime, startMemory) {
const duration = performance.now() - startTime;
const endMemory = this.getMemoryUsage();
const memoryDelta = endMemory - startMemory;
this.updateMetrics(name, {
duration,
memoryDelta,
success: true,
timestamp: Date.now()
});
}
recordFailure(name, startTime, startMemory, error) {
const duration = performance.now() - startTime;
const endMemory = this.getMemoryUsage();
const memoryDelta = endMemory - startMemory;
this.updateMetrics(name, {
duration,
memoryDelta,
success: false,
error: error.message,
timestamp: Date.now()
});
}
updateMetrics(name, measurement) {
if (!this.metrics.has(name)) {
this.metrics.set(name, {
count: 0,
totalDuration: 0,
totalMemoryDelta: 0,
successCount: 0,
failureCount: 0,
measurements: []
});
}
const metric = this.metrics.get(name);
metric.count++;
metric.totalDuration += measurement.duration;
metric.totalMemoryDelta += measurement.memoryDelta;
if (measurement.success) {
metric.successCount++;
} else {
metric.failureCount++;
}
metric.measurements.push(measurement);
// 只保留最近100次测量
if (metric.measurements.length > 100) {
metric.measurements.shift();
}
}
getMetrics(name) {
const metric = this.metrics.get(name);
if (!metric) return null;
return {
name,
count: metric.count,
averageDuration: metric.totalDuration / metric.count,
averageMemoryDelta: metric.totalMemoryDelta / metric.count,
successRate: metric.successCount / metric.count,
failureRate: metric.failureCount / metric.count,
recentMeasurements: metric.measurements.slice(-10)
};
}
getAllMetrics() {
const result = {};
for (const name of this.metrics.keys()) {
result[name] = this.getMetrics(name);
}
return result;
}
getMemoryUsage() {
if (typeof performance !== 'undefined' && performance.memory) {
return performance.memory.usedJSHeapSize;
}
return 0;
}
reset(name) {
if (name) {
this.metrics.delete(name);
} else {
this.metrics.clear();
}
}
}
// 使用性能监控
const monitor = new AsyncPerformanceMonitor();
async function demonstratePerformanceMonitoring() {
// 监控数据获取操作
const userData = await monitor.measure('fetchUser', async () => {
await delay(Math.random() * 1000 + 500);
return { id: 1, name: 'John Doe' };
});
// 监控数据处理操作
const processedData = await monitor.measure('processData', async () => {
await delay(Math.random() * 500 + 200);
return { ...userData, processed: true };
});
// 模拟一些失败的操作
for (let i = 0; i < 5; i++) {
try {
await monitor.measure('riskyOperation', async () => {
await delay(100);
if (Math.random() < 0.3) {
throw new Error('随机失败');
}
return 'success';
});
} catch (error) {
// 忽略错误,继续测试
}
}
// 查看性能指标
console.log('性能指标:');
console.log(monitor.getAllMetrics());
}
// demonstratePerformanceMonitoring();
本章总结
本章深入探讨了JavaScript的异步编程:
- 异步编程基础:理解了事件循环、异步编程的必要性和发展历程
- 回调函数:学习了回调函数的使用方法和回调地狱问题
- Promise:掌握了Promise的创建、链式调用和静态方法
- async/await:学习了现代异步编程语法,包括错误处理和并发控制
- 实际应用:通过HTTP客户端、数据加载器和重试机制展示了实际应用场景
- 性能优化:了解了异步编程的最佳实践和性能监控方法
异步编程是现代JavaScript开发的核心技能,特别是在处理网络请求、文件操作和用户交互时。掌握Promise和async/await语法,能够编写更清晰、更易维护的异步代码。
下一章我们将学习DOM操作和事件处理,这是前端开发的重要基础。