异步迭代器与生成器
迭代器(Iterator)
迭代器的概念
迭代器是一个对象,它提供了一个 next() 方法,用于遍历集合中的元素。每次调用 next() 方法都会返回一个包含 value 和 done 属性的对象。
迭代器的实现
javascript
// 自定义迭代器
function createIterator(items) {
let index = 0;
return {
next() {
return index < items.length
? { value: items[index++], done: false }
: { value: undefined, done: true };
}
};
}
// 使用迭代器
const iterator = createIterator(['a', 'b', 'c']);
console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: 'b', done: false }
console.log(iterator.next()); // { value: 'c', done: false }
console.log(iterator.next()); // { value: undefined, done: true }可迭代对象(Iterable)
可迭代对象的概念
可迭代对象是实现了 Symbol.iterator 方法的对象,该方法返回一个迭代器。
常见的可迭代对象
- 数组(Array)
- 字符串(String)
- 集合(Set)
- 映射(Map)
- arguments 对象
- NodeList 对象
自定义可迭代对象
javascript
// 自定义可迭代对象
const customIterable = {
items: ['a', 'b', 'c'],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
return index < this.items.length
? { value: this.items[index++], done: false }
: { value: undefined, done: true };
}
};
}
};
// 使用 for...of 循环遍历
for (const item of customIterable) {
console.log(item); // 输出: a, b, c
}生成器(Generator)
生成器的概念
生成器是一种特殊的函数,它可以暂停执行并在稍后继续执行。生成器函数使用 function* 语法定义,使用 yield 关键字暂停执行。
生成器的基本使用
javascript
// 生成器函数
function* generatorFunction() {
yield 'Hello';
yield 'World';
return 'End';
}
// 创建生成器对象
const generator = generatorFunction();
console.log(generator.next()); // { value: 'Hello', done: false }
console.log(generator.next()); // { value: 'World', done: false }
console.log(generator.next()); // { value: 'End', done: true }生成器的特点
- 惰性求值:生成器函数在调用
next()方法时才会执行 - 状态保存:生成器会保存函数的执行状态
- 可迭代:生成器对象是可迭代的,可以使用
for...of循环遍历 - 双向通信:可以通过
next()方法向生成器传递值
生成器与迭代器的关系
生成器函数返回的生成器对象既是迭代器,也是可迭代对象。
javascript
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
const generator = generatorFunction();
// 作为迭代器使用
console.log(generator.next()); // { value: 1, done: false }
// 作为可迭代对象使用
for (const value of generatorFunction()) {
console.log(value); // 输出: 1, 2, 3
}异步迭代器(Async Iterator)
异步迭代器的概念
异步迭代器是一个对象,它提供了一个 next() 方法,该方法返回一个 Promise,解析为包含 value 和 done 属性的对象。
异步迭代器的实现
javascript
// 自定义异步迭代器
function createAsyncIterator(items) {
let index = 0;
return {
next() {
return Promise.resolve()
.then(() => {
return index < items.length
? { value: items[index++], done: false }
: { value: undefined, done: true };
});
}
};
}
// 使用异步迭代器
const asyncIterator = createAsyncIterator(['a', 'b', 'c']);
asyncIterator.next()
.then(result => console.log(result)); // { value: 'a', done: false }
asyncIterator.next()
.then(result => console.log(result)); // { value: 'b', done: false }
asyncIterator.next()
.then(result => console.log(result)); // { value: 'c', done: false }
asyncIterator.next()
.then(result => console.log(result)); // { value: undefined, done: true }异步可迭代对象(Async Iterable)
异步可迭代对象的概念
异步可迭代对象是实现了 Symbol.asyncIterator 方法的对象,该方法返回一个异步迭代器。
自定义异步可迭代对象
javascript
// 自定义异步可迭代对象
const asyncIterable = {
items: ['a', 'b', 'c'],
[Symbol.asyncIterator]() {
let index = 0;
return {
next: () => {
return Promise.resolve()
.then(() => {
return index < this.items.length
? { value: this.items[index++], done: false }
: { value: undefined, done: true };
});
}
};
}
};
// 使用 for await...of 循环遍历
async function iterateAsync() {
for await (const item of asyncIterable) {
console.log(item); // 输出: a, b, c
}
}
iterateAsync();异步生成器(Async Generator)
异步生成器的概念
异步生成器是一种特殊的生成器函数,它可以使用 await 关键字,返回一个异步生成器对象。异步生成器函数使用 async function* 语法定义。
异步生成器的基本使用
javascript
// 异步生成器函数
async function* asyncGeneratorFunction() {
yield 'Hello';
await new Promise(resolve => setTimeout(resolve, 1000));
yield 'World';
return 'End';
}
// 创建异步生成器对象
const asyncGenerator = asyncGeneratorFunction();
// 使用异步生成器
asyncGenerator.next()
.then(result => console.log(result)); // { value: 'Hello', done: false }
asyncGenerator.next()
.then(result => console.log(result)); // { value: 'World', done: false }
asyncGenerator.next()
.then(result => console.log(result)); // { value: 'End', done: true }
// 使用 for await...of 循环遍历
async function iterateAsyncGenerator() {
for await (const value of asyncGeneratorFunction()) {
console.log(value); // 输出: Hello, World
}
}
iterateAsyncGenerator();实际应用场景
1. 处理异步数据流
javascript
// 从 API 分批获取数据
async function* fetchDataInBatches(url, batchSize) {
let page = 1;
while (true) {
const response = await fetch(`${url}?page=${page}&size=${batchSize}`);
const data = await response.json();
if (data.length === 0) {
return;
}
yield data;
page++;
}
}
// 使用异步生成器
async function processData() {
for await (const batch of fetchDataInBatches('https://api.example.com/data', 10)) {
console.log(`Processing batch of ${batch.length} items`);
// 处理数据...
}
}
processData();2. 处理文件流
javascript
// 读取大文件
const fs = require('fs');
const { Readable } = require('stream');
async function* readFileInChunks(filePath, chunkSize) {
const stream = fs.createReadStream(filePath, { highWaterMark: chunkSize });
for await (const chunk of stream) {
yield chunk;
}
}
// 使用异步生成器
async function processFile() {
for await (const chunk of readFileInChunks('large-file.txt', 1024)) {
console.log(`Processing chunk of ${chunk.length} bytes`);
// 处理数据...
}
}
processFile();3. 实现异步迭代器接口
javascript
// 实现异步迭代器接口的类
class AsyncRange {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.asyncIterator]() {
let current = this.start;
return {
next: async () => {
await new Promise(resolve => setTimeout(resolve, 100)); // 模拟异步操作
if (current < this.end) {
return { value: current++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
}
// 使用异步迭代器
async function iterateRange() {
for await (const value of new AsyncRange(1, 5)) {
console.log(value); // 输出: 1, 2, 3, 4
}
}
iterateRange();异步迭代器与生成器的优势
- 简化异步代码:使用
for await...of循环可以使异步代码更简洁易读 - 惰性求值:只在需要时才获取数据,节省内存
- 可组合性:可以轻松组合多个异步操作
- 错误处理:可以使用 try-catch 处理异步迭代过程中的错误
错误处理
生成器中的错误处理
javascript
function* generatorWithError() {
try {
yield 'Hello';
throw new Error('Generator error');
yield 'World'; // 不会执行
} catch (error) {
yield `Caught error: ${error.message}`;
}
}
const generator = generatorWithError();
console.log(generator.next()); // { value: 'Hello', done: false }
console.log(generator.next()); // { value: 'Caught error: Generator error', done: false }
console.log(generator.next()); // { value: undefined, done: true }
// 从外部抛出错误
generator.throw(new Error('External error'));异步生成器中的错误处理
javascript
async function* asyncGeneratorWithError() {
try {
yield 'Hello';
await new Promise((resolve, reject) => setTimeout(() => reject(new Error('Async error')), 1000));
yield 'World'; // 不会执行
} catch (error) {
yield `Caught error: ${error.message}`;
}
}
async function iterateAsyncGenerator() {
try {
for await (const value of asyncGeneratorWithError()) {
console.log(value); // 输出: Hello, Caught error: Async error
}
} catch (error) {
console.error('Outer error:', error);
}
}
iterateAsyncGenerator();总结
- 迭代器:提供
next()方法,用于遍历集合中的元素 - 可迭代对象:实现了
Symbol.iterator方法的对象 - 生成器:使用
function*定义的函数,可以暂停和恢复执行 - 异步迭代器:提供返回 Promise 的
next()方法 - 异步可迭代对象:实现了
Symbol.asyncIterator方法的对象 - 异步生成器:使用
async function*定义的函数,可以使用await关键字
异步迭代器与生成器是 JavaScript 中处理异步操作的强大工具,它们可以使异步代码更简洁、更易读,并且提供了一种统一的方式来处理同步和异步数据流。