ES6 新增了 Generator(生成器)这一特性,它是一种强大且灵活的函数类型。Generator 函数可以产生多次的值,每次产生一个值时可以暂停函数的执行,并且在需要时可以从上次暂停的位置继续执行。
特性:
- 暂停和恢复执行: Generator 函数在执行过程中可以暂停并保存当前的执行状态,然后在需要时恢复执行。
- 可迭代和可遍历: Generator 函数可以像数组一样被迭代和遍历。
- 惰性求值: Generator 函数的值是惰性求值的,只有在需要时才会被计算和返回。
- 控制流: Generator 函数可以控制代码的执行流程,使得异步代码的处理更加简洁和清晰。
定义 Generator 函数:
Generator 函数的定义与普通函数类似,但是在 function 关键字后面加上一个 *
符号,并且在函数体内部使用 yield
关键字来暂停函数的执行。
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = myGenerator();
console.log(gen.next()); // 输出: { value: 1, done: false }
console.log(gen.next()); // 输出: { value: 2, done: false }
console.log(gen.next()); // 输出: { value: 3, done: false }
console.log(gen.next()); // 输出: { value: undefined, done: true }
使用 Generator 函数:
Generator 函数可以像普通函数一样被调用,也可以通过 next()
方法来逐步执行函数体,并获取函数的返回值。
function* myGenerator() {
let count = 0;
while (true) {
yield count++;
}
}
const gen = myGenerator();
console.log(gen.next().value); // 输出: 0
console.log(gen.next().value); // 输出: 1
console.log(gen.next().value); // 输出: 2
控制流的应用:
Generator 函数可以用来控制异步代码的执行流程,使得异步操作更加简洁和可读。
function* fetchData() {
try {
const data = yield fetch('https://api.example.com/data');
const json = yield data.json();
console.log(json);
} catch (error) {
console.error(error);
}
}
function run(generator) {
const gen = generator();
function handleResult(result) {
if (result.done) return;
result.value.then(data => {
handleResult(gen.next(data));
}).catch(error => {
gen.throw(error);
});
}
handleResult(gen.next());
}
run(fetchData);
在上面的例子中,fetchData
函数使用了 Generator 的特性来处理异步数据请求。run
函数负责控制 Generator 函数的执行流程,使得异步操作可以按照代码的顺序执行。