闽公网安备 35020302035485号
function* myGenerator() {
// Generator 函数体
}
Generator 函数可以使用 yield 语句来定义要生成的值序列。每当执行到 yield 语句时,Generator 函数会暂停执行并返回一个包含当前生成值的对象,随后执行流程被挂起,等待下一次调用生成器函数。它的返回值是一个迭代器,这个迭代器可以通过调用 next() 方法来获取下一个生成值。当 Generator 函数中所有的 yield 语句都已经执行完成后,返回的迭代器的 done 属性为 true,表示生成器函数已经结束(这里的流程描述比较抽象,我们后面用实际案例讲解会好一点)。function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
调用 Generator 函数并不会执行函数内部的代码,而是返回一个迭代器对象,通过调用这个对象的 next() 方法来执行函数的代码,并返回一个由 yield 表达式返回的值:// 堆代码 duidaima.com
const myGeneratorIterator = myGenerator();
console.log(myGeneratorIterator.next()); // 输出 { value: 1, done: false }
console.log(myGeneratorIterator.next()); // 输出 { value: 2, done: false }
console.log(myGeneratorIterator.next()); // 输出 { value: 3, done: false }
console.log(myGeneratorIterator.next()); // 输出 { value: undefined, done: true }
Generator 函数在执行过程中,遇到 yield 表达式时会暂停函数的执行,并这个表达式的值返回给调用者。当再次调用 next() 方法时,函数会从暂停的地方继续执行;我们可以在函数中 return 一个最终的返回值,这个值会被包装在一个包含 value 和 done 属性的对象中返回:function* myGenerator() {
console.log('Start');
yield 1;
console.log('Middle');
yield 2;
console.log('End');
return 'Done';
}
const myGeneratorIterator = myGenerator();
console.log(myGeneratorIterator.next()); // 输出 Start, { value: 1, done: false }
console.log(myGeneratorIterator.next()); // 输出 Middle, { value: 2, done: false }
console.log(myGeneratorIterator.next()); // 输出 End, { value: 'Done', done: true }
function* foo() {
yield 1;
yield 2;
}
function* bar() {
yield* foo();
yield 3;
}
for (let value of bar()) {
console.log(value); // 输出 1, 2, 3
}
在这个例子中,Generator 函数 bar() 中的 yield* foo() 表达式会调用 foo() 函数并将其迭代结果依次返回给 bar() 函数。function* foo() {
let x = yield;
yield x * 2;
}
let gen = foo();
gen.next(); // 启动生成器
gen.next(10); // 传递参数 10,输出 20
在这个例子中,foo() 函数会在第一次调用 next() 方法时停止在第一个 yield 语句处,等待外部传入的数据。然后,第二次调用 next() 方法时将外部传入的数据作为 yield 表达式的值,再向下执行,直到遇到下一个 yield 表达式返回数据。function* myGenerator() {
const result1 = yield new Promise((resolve) => setTimeout(() => resolve('first'), 1000));
console.log(result1);
const result2 = yield new Promise((resolve) => setTimeout(() => resolve('second'), 2000));
console.log(result2);
const result3 = yield new Promise((resolve) => setTimeout(() => resolve('third'), 3000));
console.log(result3);
}
const generator = myGenerator();
const promise = generator.next().value;
promise.then((result) => generator.next(result).value)
.then((result) => generator.next(result).value)
.then((result) => generator.next(result).value);
看起来是不是和 async/await 的作用很像,下面是他们两种语法之间的一些对比:2.可读性较差:相比于 async/await,Generator 函数的语法和代码结构相对较复杂,可读性不如 async/await。
function* fetchAllData() {
const data1 = yield fetch('api1');
const data2 = yield fetch('api2');
const data3 = yield fetch('api3');
return [data1, data2, data3];
}
function run(generator) {
const iterator = generator();
function handle(iteratorResult) {
if (iteratorResult.done) {
return Promise.resolve(iteratorResult.value);
}
return Promise.resolve(iteratorResult.value)
.then(res => handle(iterator.next(res)));
}
return handle(iterator.next());
}
run(fetchAllData).then(data => {
// 处理所有数据
console.log(data);
});
处理大数据节省内存function* dataGenerator() {
let index = 0;
while (true) {
yield index++;
}
}
function* processData(data, processFn) {
for (let item of data) {
yield processFn(item);
}
}
const data = dataGenerator();
const processedData = processData(data, item => item * 2);
for (let i = 0; i < 500; i++) {
console.log(processedData.next().value);
}
实现状态机function* stateMachine() {
let state = 'start';
while (true) {
switch (state) {
case 'start':
console.log('Enter start state');
state = yield 'start';
break;
case 'middle':
console.log('Enter middle state');
state = yield 'middle';
break;
case 'end':
console.log('Enter end state');
state = yield 'end';
break;
}
}
}
const sm = stateMachine();
console.log(sm.next().value); // Enter start state
console.log(sm.next('middle').value); // Enter middle state
console.log(sm.next('end').value); // Enter end state