function* test(){
yield 'hello';
yield 'world';
return 'end';
}
var tt = test()
tt.next() // {value: "hello", done: false}
tt.next() // {value: "world", done: false}
tt.next() // {value: "end", done: false}
tt.next() // {value: undefined, done: true}
function* f() {
console.log('执行了!')
}
var generator = f();
setTimeout(function () {
generator.next()
}, 2000);
function* demo() {
console.log('Hello' + yield); // SyntaxError
console.log('Hello' + yield 123); // SyntaxError
console.log('Hello' + (yield)); // OK
console.log('Hello' + (yield 123)); // OK
}
function* demo() {
foo(yield 'a', yield 'b'); // OK
let input = yield; // OK
}
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
function* gen(){
yield 1;
yield 2;
}
var g = gen();
[...g] // [1,2]
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 }
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
function* numbers () {
yield 1
yield 2
return 3
yield 4
}
// 扩展运算符
[...numbers()] // [1, 2]
// Array.from 方法
Array.from(numbers()) // [1, 2]
// 解构赋值
let [x, y] = numbers();
x // 1
y // 2
// for...of 循环
for (let n of numbers()) {
console.log(n)
}
// 1
// 2
var g = function* () {
try {
yield;
} catch (e) {
console.log('内部捕获', e);
}
};
var i = g();
i.next();
try {
i.throw('a');
i.throw('b');
} catch (e) {
console.log('外部捕获', e);
}
// 内部捕获 a
// 外部捕获 b
var gen = function* gen(){
try {
yield console.log('a');
} catch (e) {
// ...
}
yield console.log('b');
yield console.log('c');
}
var g = gen();
g.next() // a
g.throw() // b
g.next() // c
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen();
g.next() // { value: 1, done: false }
g.return('foo') // { value: "foo", done: true }
g.next() // { value: undefined, done: true }
function* numbers () {
yield 1;
try {
yield 2;
yield 3;
} finally {
yield 4;
yield 5;
}
yield 6;
}
var g = numbers();
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.return(7) // { value: 4, done: false }
g.next() // { value: 5, done: false }
g.next() // { value: 7, done: true }
如果在 Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历。
function* foo() {
yield 'a';
yield 'b';
}
function* bar() {
yield 'x';
// 手动遍历 foo()
for (let i of foo()) {
console.log(i);
}
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// x
// a
// b
// y
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
yield 'a';
yield 'b';
yield 'y';
}
// 等同于
function* bar() {
yield 'x';
for (let v of foo()) {
yield v;
}
yield 'y';
}
for (let v of bar()){
console.log(v);
}
// "x"
// "a"
// "b"
// "y"
function* foo() {
yield 2;
yield 3;
return "foo";
}
function* bar() {
yield 1;
var v = yield* foo();
console.log("v: " + v);
yield 4;
}
var it = bar();
it.next()
// {value: 1, done: false}
it.next()
// {value: 2, done: false}
it.next()
// {value: 3, done: false}
it.next();
// "v: foo"
// {value: 4, done: false}
it.next()
// {value: undefined, done: true}
let obj = {
* myGeneratorMethod() {
···
}
// 等同于
myGeneratorMethod: function* () {
// ···
}
};
function *g() {
console.log(this)
yield 'g'
}
let foo = g()
foo.next()
// Window
// {value: "g", done: false}
function* F() {
this.a = 1;
yield this.b = 2;
yield this.c = 3;
}
var obj = {};
var f = F.call(obj);
f.next(); // Object {value: 2, done: false}
f.next(); // Object {value: 3, done: false}
f.next(); // Object {value: undefined, done: true}
obj.a // 1
obj.b // 2
obj.c // 3
function* F() {
this.a = 1;
yield this.b = 2;
yield this.c = 3;
}
var f = F.call(F.prototype);
f.next(); // Object {value: 2, done: false}
f.next(); // Object {value: 3, done: false}
f.next(); // Object {value: undefined, done: true}
f.a // 1
f.b // 2
f.c // 3
var flag = true;
var toggle = function(){
if(flag)
// show
else
// hide
flag = !flag
}
var toggle = function* () {
while (true) {
// show
yield;
// hide
yield;
}
};
function delay(msg, callback) {
setTimeout(function () {
console.log(msg)
callback()
}, 1000)
}
delay('1', function () {
delay('2', function () {
delay('3', function () {
delay('4', function () {
delay('5', function () {
console.log('done')
})
})
})
})
})
function delay(msg) {
return new Promise((resolve, reject) => {
setTimeout(function () {
console.log(msg)
resolve()
}, 1000)
})
}
delay('1')
.then(() => delay('2'))
.then(() => delay('3'))
.then(() => delay('4'))
.then(() => delay('5'))
.then(() => {
console.log('done')
})
– 上面代码耦合度高,而且要求每个异步都是Promise,不然不可行;
– 于是,Generator函数出现了,是解决此类场景的极佳办法;
function delay(msg) {
setTimeout(function () {
iter.next(msg)
}, 1000)
}
function*g() {
let result1 = yield delay('1')
console.log(result1)
let result2 = yield delay('2')
console.log(result2)
let result3 = yield delay('3')
console.log(result3)
let result4 = yield delay('4')
console.log(result4)
let result5 = yield delay('5')
console.log(result5)
console.log('done')
}
let iter = g()
iter.next()
let obj = {
a: 1,
b: 2,
c: 3,
*[Symbol.iterator]() {
yield this.c
yield this.b
yield this.a
}
}
let arr = [...obj];
arr; // [3, 2, 1]
参考文献:阮一峰es6