HLJ 发布于
2025-06-11 11:11:19
0阅读

JavaScript异步迭代与Generator详解

下一篇文章:

JavaScript模块系统简介

JavaScript 异步迭代与 Generator

异步迭代 (Asynchronous Iteration)

异步迭代是 ES2018 引入的特性,允许我们异步地遍历数据。

基本概念

  1. 异步可迭代对象 (Async Iterable): 实现了 [Symbol.asyncIterator] 方法的对象
  2. 异步迭代器 (Async Iterator): 具有 next() 方法的对象,该方法返回一个 Promise

使用 for-await-of 循环

async function processAsyncData() {
  const asyncIterable = {
    [Symbol.asyncIterator]() {
      let i = 0;
      return {
        next() {
          if (i < 3) {
            return Promise.resolve({ value: i++, done: false });
          }
          return Promise.resolve({ done: true });
        }
      };
    }
  };

  for await (const item of asyncIterable) {
    console.log(item); // 0, 1, 2
  }
}

processAsyncData();

实际应用示例

// 从网络分页获取数据
async function* fetchPages(url) {
  let nextUrl = url;
  while (nextUrl) {
    const response = await fetch(nextUrl);
    const data = await response.json();
    nextUrl = data.nextPage;
    yield data.items;
  }
}

// 使用
(async () => {
  for await (const items of fetchPages('https://api.example.com/data?page=1')) {
    console.log('Received items:', items);
    // 处理每一页的数据
  }
})();

Generator 函数

Generator 是 ES6 引入的特殊函数,可以暂停和恢复执行。

基本语法

function* generatorFunction() {
  yield 'First';
  yield 'Second';
  return 'Done';
}

const generator = generatorFunction();

console.log(generator.next()); // { value: 'First', done: false }
console.log(generator.next()); // { value: 'Second', done: false }
console.log(generator.next()); // { value: 'Done', done: true }

异步 Generator 函数

async function* asyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}

(async () => {
  for await (const value of asyncGenerator()) {
    console.log(value); // 1, 2, 3
  }
})();

实际应用示例

// 模拟从多个API顺序获取数据
async function* fetchSequentialData(urls) {
  for (const url of urls) {
    try {
      const response = await fetch(url);
      const data = await response.json();
      yield data;
    } catch (error) {
      console.error(`Failed to fetch ${url}:`, error);
      yield null;
    }
  }
}

// 使用
(async () => {
  const urls = [
    'https://api.example.com/users',
    'https://api.example.com/posts',
    'https://api.example.com/comments'
  ];
  
  for await (const data of fetchSequentialData(urls)) {
    if (data) {
      console.log('Received data:', data);
    }
  }
})();

结合使用异步迭代和 Generator

// 创建可取消的异步数据流
function createCancellableAsyncStream(sourceAsyncIterable) {
  let cancel = () => {};
  
  const asyncIterable = {
    [Symbol.asyncIterator]() {
      const iterator = sourceAsyncIterable[Symbol.asyncIterator]();
      
      return {
        async next() {
          const promise = new Promise((resolve, reject) => {
            cancel = () => reject(new Error('Stream cancelled'));
          });
          
          try {
            const result = await Promise.race([iterator.next(), promise]);
            return result;
          } catch (error) {
            return { done: true };
          }
        }
      };
    }
  };
  
  return { asyncIterable, cancel };
}

// 使用
(async () => {
  const { asyncIterable, cancel } = createCancellableAsyncStream(someAsyncDataSource);
  
  setTimeout(() => cancel(), 5000); // 5秒后取消
  
  try {
    for await (const item of asyncIterable) {
      console.log(item);
    }
  } catch (error) {
    console.log('Stream was cancelled');
  }
})();

总结

  1. 同步 Generator:

    • 使用 function* 声明
    • 使用 yield 暂停执行
    • 使用 next() 恢复执行
  2. 异步 Generator:

    • 使用 async function* 声明
    • 可以 yield await Promise
    • 使用 for await...of 遍历
  3. 异步迭代:

    • 对象实现 [Symbol.asyncIterator] 方法
    • 适用于处理异步数据流
    • for await...of 配合使用

这些特性在处理异步数据流、分页数据、实时数据源等场景非常有用,能够以同步的方式编写异步代码,提高可读性和可维护性。

当前文章内容为原创转载请注明出处:http://www.good1230.com/detail/2025-06-11/837.html
最后生成于 2025-06-13 20:53:52
下一篇文章:

JavaScript模块系统简介

此内容有帮助 ?
0