class Counter {
constructor(limit) {
this.limit = limit;
}
[Symbol.iterator]() {
let count = 1,
limit = this.limit;
return {
next() {
if (count <= limit) {
return { done: false, value: count++ };
} else {
return { done: true };
}
},
return() {
console.log('Exiting early');
return { done: true };
}
};
}
}
let counter1 = new Counter(5);
for (let i of counter1) {
if (i > 2) {
break;
}
console.log(i);
}
// 1
// 2
// Exiting early
let counter2 = new Counter(5);
try {
for (let i of counter2) {
if (i > 2) {
throw 'err';
}
console.log(i);
}
} catch(e) {}
// 1
// 2
// Exiting early
let counter3 = new Counter(5);
let [a, b] = counter3;
// Exiting early
如果迭代器没有关闭,则还可以继续从上次离开的地方继续迭代。比如,数组的迭代器就是不能关 闭的:
let a = [1, 2, 3, 4, 5];
let iter = a[Symbol.iterator]();
for (let i of iter) {
console.log(i);
if (i > 2) {
break
}
}
// 1
// 2
// 3
for (let i of iter) {
console.log(i);
}
// 4
// 5
let a = [1, 2, 3, 4, 5];
let iter = a[Symbol.iterator]();
iter.return = function () {
console.log('Exiting early');
return { done: true };
};
for (let i of iter) {
console.log(i);
if (i > 2) {
break
}
}
// 1
// 2
// 3
// 提前退出
for (let i of iter) {
console.log(i);
}
// 4
// 5
// 生成器函数声明
function* generatorFn() {}
// 生成器函数表达式
let generatorFn = function*() {}
// 作为对象字面量方法的生成器函数
let foo = {
* generatorFn() {}
}
// 作为类实例方法的生成器函数
class Foo {
* generatorFn() {}
}
// 作为类静态方法的生成器函数
class Bar {
static* generatorFn() {}
}
注意 箭头函数不能用来定义生成器函数。 标识生成器函数的星号不受两侧空格的影响
控制并发数
async function* asyncPool(concurrency, iterable, iteratorFn) {
const executing = new Set();
async function consume() {
const [promise, value] = await Promise.race(executing);
executing.delete(promise);
return value;
}
for (const item of iterable) {
// Wrap iteratorFn() in an async fn to ensure we get a promise.
// Then expose such promise, so it's possible to later reference and
// remove it from the executing pool.
const promise = (async () => await iteratorFn(item, iterable))().then(
value => [promise, value]
);
executing.add(promise);
if (executing.size >= concurrency) {
yield await consume();
}
}
while (executing.size) {
yield await consume();
}
}
async function asyncTask(item, iterable) {
// 模拟异步操作
await new Promise(resolve => setTimeout(() => {
console.log(`Task ${item} preparing`);
resolve()
}, 1000));
console.log(`Task ${item} completed`);
return item
}
async function main() {
const items = [1, 2, 3, 4, 5];
const concurrency = 2;
for await (const result of asyncPool(concurrency, items, asyncTask)) {
// do something with result
console.log(`Result: ${result}`);
}
}
main();