异步迭代是 ES2018 引入的特性,允许我们异步地遍历数据。
[Symbol.asyncIterator]
方法的对象next()
方法的对象,该方法返回一个 Promisefor-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 是 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 }
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);
}
}
})();
// 创建可取消的异步数据流
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');
}
})();
同步 Generator:
function*
声明yield
暂停执行next()
恢复执行异步 Generator:
async function*
声明yield await
Promisefor await...of
遍历异步迭代:
[Symbol.asyncIterator]
方法for await...of
配合使用这些特性在处理异步数据流、分页数据、实时数据源等场景非常有用,能够以同步的方式编写异步代码,提高可读性和可维护性。