Generator 函数是 ES6 中引入的一种新的函数类型,它可以在函数执行的过程中暂停和恢复,从而使得函数的执行过程可以分成多个阶段进行,这对于异步编程非常有用。在 ECMAScript 2018 中,Generator 函数引入了一些新的特性,本篇文章将介绍这些新特性以及它们的使用场景。
Generator 函数的基本语法和用法
Generator 函数的基本语法和用法可以参考以下示例代码:
// www.javascriptcn.com code example
function* myGenerator() {
yield 'a';
yield 'b';
yield 'c';
}
const gen = myGenerator();
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: 'c', done: false }
console.log(gen.next()); // { value: undefined, done: true }在上面的示例代码中,myGenerator 是一个 Generator 函数,它通过 yield 关键字可以在函数执行的过程中暂停并返回一个值。gen 是通过 myGenerator() 调用生成的一个 Generator 对象,它可以通过调用 next() 方法来继续执行函数并获取 yield 返回的值,直到函数执行完毕。
Generator 函数的新特性
在 ECMAScript 2018 中,Generator 函数引入了以下新特性:
1. yield* 表达式
yield* 表达式可以用来在 Generator 函数中嵌套调用另一个 Generator 函数,示例代码如下:
// www.javascriptcn.com code example
function* myGenerator() {
yield 'a';
yield* anotherGenerator();
yield 'c';
}
function* anotherGenerator() {
yield 'b';
}
const gen = myGenerator();
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: 'c', done: false }
console.log(gen.next()); // { value: undefined, done: true }在上面的示例代码中,myGenerator 中通过 yield* 调用了另一个 Generator 函数 anotherGenerator,从而使得函数的执行过程可以分成多个阶段进行。
2. return 语句
Generator 函数中可以使用 return 语句来结束函数的执行,并返回一个指定的值,示例代码如下:
// www.javascriptcn.com code example
function* myGenerator() {
yield 'a';
yield 'b';
return 'c';
}
const gen = myGenerator();
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: 'c', done: true }在上面的示例代码中,myGenerator 中使用 return 语句结束了函数的执行,并返回了一个值。注意,当 Generator 函数执行完毕时,done 属性为 true。
3. throw 方法
Generator 对象上可以调用 throw 方法来抛出一个异常,示例代码如下:
// www.javascriptcn.com code example
function* myGenerator() {
try {
yield 'a';
yield 'b';
} catch (e) {
console.log(e);
}
}
const gen = myGenerator();
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.throw(new Error('error'))); // Error: error
console.log(gen.next()); // { value: undefined, done: true }在上面的示例代码中,myGenerator 中使用 try...catch 语句来捕获异常,并在捕获到异常时输出错误信息。gen 对象在执行到第二个 yield 时抛出了一个异常,然后被 try...catch 语句捕获到并输出错误信息。
Generator 函数的使用场景
Generator 函数的使用场景非常广泛,下面列举了几个常见的使用场景:
1. 异步编程
Generator 函数的暂停和恢复机制非常适合用于异步编程。通过在 Generator 函数中使用 yield 关键字来阻塞执行,然后在异步操作完成后使用 next 方法来恢复执行,可以很好地避免回调地狱和 Promise 链的问题。示例代码如下:
// www.javascriptcn.com code example
function* myGenerator() {
const result1 = yield asyncFunc1();
const result2 = yield asyncFunc2(result1);
const result3 = yield asyncFunc3(result2);
return result3;
}
function asyncFunc1() {
return new Promise(resolve => {
setTimeout(() => {
resolve('result1');
}, 1000);
});
}
function asyncFunc2(arg) {
return new Promise(resolve => {
setTimeout(() => {
resolve(`result2-${arg}`);
}, 1000);
});
}
function asyncFunc3(arg) {
return new Promise(resolve => {
setTimeout(() => {
resolve(`result3-${arg}`);
}, 1000);
});
}
const gen = myGenerator();
gen.next().value.then(result1 => {
return gen.next(result1).value;
}).then(result2 => {
return gen.next(result2).value;
}).then(result3 => {
console.log(gen.next(result3)); // { value: undefined, done: true }
});在上面的示例代码中,myGenerator 中通过 yield 关键字阻塞了执行,并在异步操作完成后通过 next 方法恢复了执行,从而实现了异步编程。
2. 生成器函数
Generator 函数可以用来创建一个可迭代对象,从而可以很方便地生成一系列的值。示例代码如下:
// www.javascriptcn.com code example
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for (const num of range(1, 5)) {
console.log(num);
}在上面的示例代码中,range 函数通过 yield 关键字生成了一个可迭代对象,从而可以很方便地生成一系列的数字。
3. 控制流程
Generator 函数的暂停和恢复机制可以用来控制代码的流程,从而实现一些复杂的操作。示例代码如下:
// www.javascriptcn.com code example
function* myGenerator() {
const num = yield 'input a number:';
if (num > 0) {
yield 'positive number';
} else if (num < 0) {
yield 'negative number';
} else {
yield 'zero';
}
}
const gen = myGenerator();
console.log(gen.next().value); // input a number:
console.log(gen.next(5).value); // positive number在上面的示例代码中,myGenerator 中通过 yield 关键字暂停了执行,并等待输入一个数字。然后根据输入的数字返回不同的结果。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d2aaa1a941bf7134525f8e