全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 10 分钟 ✍️ juanwangdev

异步设计模式

JavaScript异步编程是前端开发的核心技能,掌握异步设计模式是构建高性能应用的关键。

异步基础模式

回调模式

JavaScript
// 基础回调
function fetchData(url, callback) {
  setTimeout(() => {
    callback(null, { data: 'result' });
  }, 1000);
}

// 错误优先回调(Node.js风格)
fetchData('/api', (error, data) => {
  if (error) {
    console.error(error);
    return;
  }
  console.log(data);
});

// 回调地狱问题
fetchUser(userId, (error, user) => {
  fetchOrders(user.id, (error, orders) => {
    fetchOrderDetails(orders[0].id, (error, details) => {
      // 嵌套层级过深
    });
  });
});

Promise模式

JavaScript
// Promise封装
function fetchData(url) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ data: 'result' });
    }, 1000);
  });
}

// 链式调用解决回调地狱
fetchUser(userId)
  .then(user => fetchOrders(user.id))
  .then(orders => fetchOrderDetails(orders[0].id))
  .then(details => console.log(details))
  .catch(error => console.error(error));

// 并行处理
Promise.all([
  fetchUser(userId),
  fetchOrders(userId),
  fetchNotifications(userId)
]).then(([user, orders, notifications]) => {
  // 全部完成
});

// 竞争处理
Promise.race([
  fetchFromServer1(),
  fetchFromServer2()
]).then(result => {
  // 第一个完成的结果
});

Async/Await模式

JavaScript
// 基础语法
async function fetchUserOrders(userId) {
  try {
    const user = await fetchUser(userId);
    const orders = await fetchOrders(user.id);
    return orders;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

// 并行执行
async function fetchAll(userId) {
  const [user, orders, notifications] = await Promise.all([
    fetchUser(userId),
    fetchOrders(userId),
    fetchNotifications(userId)
  ]);
  return { user, orders, notifications };
}

异步流程控制模式

异步队列模式

JavaScript
class AsyncQueue {
  constructor(concurrency = 1) {
    this.concurrency = concurrency;
    this.running = 0;
    this.queue = [];
  }

  async add(task) {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, resolve, reject });
      this.process();
    });
  }

  async process() {
    while (this.running < this.concurrency && this.queue.length > 0) {
      this.running++;
      const { task, resolve, reject } = this.queue.shift();
      try {
        const result = await task();
        resolve(result);
      } catch (error) {
        reject(error);
      } finally {
        this.running--;
        this.process();
      }
    }
  }
}

// 使用:限制并发数
const queue = new AsyncQueue(3);
for (let i = 0; i < 10; i++) {
  queue.add(() => fetchData(`/api/${i}`));
}

异步重试模式

JavaScript
async function retry(fn, options = {}) {
  const { maxRetries = 3, delay = 1000, backoff = 2 } = options;
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      if (i < maxRetries - 1) {
        await sleep(delay * Math.pow(backoff, i));
      }
    }
  }

  throw lastError;
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// 使用
await retry(() => fetchData('/api/data'), {
  maxRetries: 3,
  delay: 500,
  backoff: 2
});

超时控制模式

JavaScript
// Promise超时
function withTimeout(promise, ms) {
  const timeout = new Promise((_, reject) => {
    setTimeout(() => reject(new Error('Timeout')), ms);
  });
  return Promise.race([promise, timeout]);
}

// 使用
try {
  const data = await withTimeout(fetchData('/api'), 5000);
} catch (error) {
  if (error.message === 'Timeout') {
    console.log('请求超时');
  }
}

// AbortController取消
async function fetchWithAbort(url, signal) {
  const response = await fetch(url, { signal });
  return response.json();
}

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

try {
  await fetchWithAbort('/api/data', controller.signal);
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('请求已取消');
  }
}

高级异步模式

异步迭代器模式

JavaScript
// 异步生成器
async function* fetchPaginatedData(baseUrl) {
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const response = await fetch(`${baseUrl}?page=${page}`);
    const data = await response.json();

    yield* data.items;

    hasMore = data.hasMore;
    page++;
  }
}

// 使用
for await (const item of fetchPaginatedData('/api/items')) {
  console.log(item);
}

// 异步迭代器类
class AsyncDataIterator {
  constructor(fetcher) {
    this.fetcher = fetcher;
    this.index = 0;
    this.data = [];
  }

  [Symbol.asyncIterator]() {
    return {
      next: async () => {
        if (this.index >= this.data.length) {
          this.data = await this.fetcher();
          this.index = 0;
        }
        if (this.data.length === 0) {
          return { done: true };
        }
        return { value: this.data[this.index++], done: false };
      }
    };
  }
}

异步事件发射器

JavaScript
class AsyncEventEmitter {
  constructor() {
    this.events = new Map();
  }

  on(event, handler) {
    if (!this.events.has(event)) {
      this.events.set(event, []);
    }
    this.events.get(event).push(handler);
  }

  async emit(event, ...args) {
    const handlers = this.events.get(event) || [];
    await Promise.all(handlers.map(handler => handler(...args)));
  }

  once(event, handler) {
    const wrapper = async (...args) => {
      await handler(...args);
      this.off(event, wrapper);
    };
    this.on(event, wrapper);
  }

  off(event, handler) {
    const handlers = this.events.get(event);
    if (handlers) {
      const index = handlers.indexOf(handler);
      if (index > -1) handlers.splice(index, 1);
    }
  }
}

// 使用
const emitter = new AsyncEventEmitter();
emitter.on('data', async (data) => {
  await process(data);
});
await emitter.emit('data', { id: 1 });

异步缓存模式

JavaScript
class AsyncCache {
  constructor(fetcher, ttl = 60000) {
    this.fetcher = fetcher;
    this.ttl = ttl;
    this.cache = new Map();
    this.pending = new Map();
  }

  async get(key) {
    const cached = this.cache.get(key);
    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.value;
    }

    // 防止重复请求
    if (this.pending.has(key)) {
      return this.pending.get(key);
    }

    const promise = this.fetcher(key).then(value => {
      this.cache.set(key, { value, timestamp: Date.now() });
      this.pending.delete(key);
      return value;
    });

    this.pending.set(key, promise);
    return promise;
  }

  invalidate(key) {
    this.cache.delete(key);
  }
}

// 使用
const cache = new AsyncCache(fetchData, 30000);
const data1 = await cache.get('user-1'); // 发起请求
const data2 = await cache.get('user-1'); // 返回缓存

并发控制模式

并发池

JavaScript
async function pool(tasks, concurrency) {
  const results = [];
  const executing = new Set();

  for (const task of tasks) {
    const promise = Promise.resolve().then(() => task());
    results.push(promise);
    executing.add(promise);

    const cleanup = () => executing.delete(promise);
    promise.then(cleanup, cleanup);

    if (executing.size >= concurrency) {
      await Promise.race(executing);
    }
  }

  return Promise.all(results);
}

// 使用:同时最多执行3个任务
const tasks = urls.map(url => () => fetch(url));
const results = await pool(tasks, 3);

节流与防抖

JavaScript
// 防抖:延迟执行,重复调用重置计时
function debounce(fn, delay) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 节流:固定间隔执行
function throttle(fn, interval) {
  let lastTime = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      lastTime = now;
      return fn.apply(this, args);
    }
  };
}

// 异步节流:保证上一个完成后再执行
async function asyncThrottle(fn, interval) {
  let lastTime = 0;
  let pending = false;

  return async function (...args) {
    if (pending) return;

    const now = Date.now();
    if (now - lastTime < interval) {
      return;
    }

    pending = true;
    try {
      lastTime = Date.now();
      return await fn.apply(this, args);
    } finally {
      pending = false;
    }
  };
}

要点总结

  1. 回调→Promise→Async/Await:异步编程演进,代码更简洁
  2. 异步队列:控制并发数,避免资源耗尽
  3. 重试机制:提高可靠性,配合退避策略
  4. 超时控制:防止无限等待,AbortController可取消
  5. 异步迭代器:处理分页、流式数据的利器
  6. 并发池:高效处理批量异步任务

存放路径:articles/JS/专家/设计模式与架构思想/异步设计模式.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 工厂模式与单例模式
下一篇 → 模块化设计原则
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库