Generator 函数是 ES6 提供的一种异步编程解决
Generator函数是一个状态机,封装了多个内部状态
Generator函数还是一个遍历器对象生成函数,返回遍历器对象
1.function关键字与函数名之间有一个星号
2.函数体内部使用yield表达式,定义不同的内部状态
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
//调用函数不会立即执行,而是返回遍历器对象
var hw = helloWorldGenerator();
hw.next() // { value: 'hello', done: false }
hw.next() // { value: 'world', done: false }
hw.next() // { value: 'ending', done: true }
hw.next() // { value: undefined, done: true }
调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。
yield表达式就是暂停标志。
yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行。
使用yield需注意:
(1).yield表达式只能用在 Generator 函数里面
(2).yield表达式如果用在另一个表达式之中,必须放在圆括号里面
function* demo() {
console.log('Hello' + yield); // SyntaxError
console.log('Hello' + yield 123); // SyntaxError
console.log('Hello' + (yield)); // OK
console.log('Hello' + (yield 123)); // OK
}
yield与return的异同:
(1).next()遇到yield与return均会暂停
(2).函数内部只能有一个return,但是可以有多个yield
(3).yield能够记录位置,下一次从该位置继续执行,return不会记录位置
next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
//第一次调用b的next方法时,返回x+1的值6;
第二次调用next方法,将上一次yield表达式的值设为12,因此y等于24,返回y / 3的值8;
第三次调用next方法,将上一次yield表达式的值设为13,因此z等于13,这时x等于5,y等于24,所以return语句的值等于42
for…of循环可以自动遍历 Generator 函数运行时生成的Iterator对象
function* foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
}
for (let v of foo()) {
console.log(v);
}
// 1 2 3 4 5
//注意:next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象
yield*表达式,用来在一个Generator函数里执行另一个Generator函数。
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
yield 'a';
yield 'b';
yield 'y';
}
使用for…of循环实现斐波那契数列
function* fibonacci() {
let [prev, curr] = [0, 1];
for (;;) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
for (let n of fibonacci()) {
if (n > 1000) break;
console.log(n);
}
将异步操作写在yield表达式里面,需要异步操作的后续操作放在yield表达式下面,等到调用next方法时再执行
function* loadUI() {
showLoadingScreen();
yield loadUIDataAsynchronously();
hideLoadingScreen();
}
var loader = loadUI();
// 加载UI
loader.next()
// 卸载UI
loader.next()
如果程序调用某个方法,等待其执行全部处理后才能继续执行,我们称其为同步的。相反,在处理完成之前就返回调用方法则是异步的。
异步编程一般会在方法执行之前注册一个事件,等待方法真正执行完成后通过该事件获取返回结果
异步编程适用于高IO的场景
ES6 诞生以前,异步编程的方法,大概有下面四种:
(1)回调函数
(2)事件监听
(3)发布/订阅者
(4)Promise对象
Generator 函数将 JavaScript 异步编程带入了一个全新的阶段
https://es6.ruanyifeng.com/#docs/generator
|
https://blog.csdn.net/ganyingxie123456/article/details/78152770?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.control