您的位置:首页 > 其它

ES6 Generator

2017-10-18 16:54 162 查看
ES6 中规定, Generator 函数内部使用 this 无效,而且不能使用 new 关键字来获取 Generator 的一个实例。

1、内部使用 this

如下方法可以使得 Generator 内部的 this 关键字有效:

function* a() {
this.a = 1;
yield "hello";
yield "world"
};

let b = a();
console.log(b.a, b.next(), b.next());
//undefined { value: 'hello', done: false } { value: 'world', done: false }

let c = a.call(a.prototype);
console.log( c.next(), c.next(), c.a)
//{ value: 'hello', done: false } { value: 'world', done: false } 1


这样,执行两次 next() 将 Generator 里面的数据执行完后,将 this 绑定到 a 的原型上面去。若还没有使用 next() 处理完 Generator 里面的数据,this 是不会绑定到 a.prototype 上去的。

2、状态机

Generator 是实现状态机的最佳结构,比如如下代码:

var clock = function* () {
while (true) {
console.log('Tick!');
yield;
console.log('Tock!');
yield;
}
};
let a = clock();
a.next(); //Tick!
a.next(); //Tock!
a.next(); //Tick!
a.next(); //Tock!
a.next(); //Tick!

let b = clock();
b.next(); //Tick!
b.next(); //Tock!
a.next(); //Tock!


3、控制流管理

利用for…of循环会自动依次执行yield命令的特性,提供一种更一般的控制流管理的方法。

ES6 之前,进行流程控制,我们大多数使用的是回调函数:

function step1(val, fun) {
console.log("step" + val++);
if (typeof fun == "function") fun(val);
return val;
}
function step2(val, fun) {
console.log("step" + val++);
if (typeof fun == "function") fun(val);
return val;
}
function step3(val, fun) {
console.log("step" + val++);
if (typeof fun == "function") fun(val);
return val;
}
function step4(val, fun) {
console.log("step" + val++);
if (typeof fun == "function") fun(val);
return val;
}
//原本流程控制需要使用回调函数的方式来实现,如下:
function task(init) {
step1(init, function (val1) {
step2(val1, function (val2) {
step3(val2, function (val3) {
step4(val3, function (val4) {
//......
})
})
})
});
}
task(1);

//采用 Promise 改写上面的代码:
Promise.resolve(step1(1))
.then(val => step2(val))
.then(val => step3(val))
.then(val => step4(val));

//Generator 函数实现上面代码逻辑
function* rangeTask(initVal) {
try {
let val1 = yield step1(initVal);
let val2 = yield step2(val1);
let val3 = yield step3(val2);
let val4 = yield step4(val3);
//...
} catch (e) {
console.log(e)
}
}

function scheduler(task) {
let obj = task.next(task.value);
if (!obj.done) {
task.value = obj.value;
scheduler(task);
}
}

scheduler(rangeTask(1));


注意:

上面这种做法,只适合同步操作,即所有的task都必须是同步的,不能有异步操作。因为这里的代码一得到返回值,就继续往下执行,没有判断异步操作何时完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  es6 Generator