异步编程概述

什么是异步编程

异步编程是一种编程范式,允许程序在等待某些操作完成时继续执行其他任务,而不是阻塞整个程序的执行。在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的异步编程:

  1. 异步编程基础:理解了事件循环、异步编程的必要性和发展历程
  2. 回调函数:学习了回调函数的使用方法和回调地狱问题
  3. Promise:掌握了Promise的创建、链式调用和静态方法
  4. async/await:学习了现代异步编程语法,包括错误处理和并发控制
  5. 实际应用:通过HTTP客户端、数据加载器和重试机制展示了实际应用场景
  6. 性能优化:了解了异步编程的最佳实践和性能监控方法

异步编程是现代JavaScript开发的核心技能,特别是在处理网络请求、文件操作和用户交互时。掌握Promise和async/await语法,能够编写更清晰、更易维护的异步代码。

下一章我们将学习DOM操作和事件处理,这是前端开发的重要基础。