概念和基本操作
1,实质是一个状态机,在生成器里面可以包含多种状态,可以暂停。
2,执行generator函数会返回一个遍历器对象,可以一次遍历函数内部的每一个状态
3,通过关键字yield来定义状态,通过next()来遍历状态。
举个栗子:
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}
参数传递和状态遍历
注意的点:
1,next()参数传递。举个栗子:
function* foo(x){
var y = 2 * (yield (x+1));
var z = yield (y/3);
return (x+y+z)
}
var a = foo(5);
a.next();//{value:6.done:false}
a.next();//{value:NaN.done:false}
a.next();//{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()语句只返回 yield 后面表达式的值,即 5+1=6;b.next(12)这次的参数 12 才会变为 yield(x+1)的返回值,所以 y = 2*12=24;且要 执行第二条 yield 语句,打印出的 value 值是 24/3=8;此时 z没有被赋值,因为在等待 yield(y/3)的返回值,也就是下一次next 的参数,所以b.next(13),这里的 13 就是整体 yield(y/3) 语句的返回值,z=13,且执行最后一条返回语句,5+24+13=42
2,可以通过 for…of 来遍历 yield 后面的值,也就是可以拿到所有状态,但是最后的 return语句不会执行。 举个栗子
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
用途
1,异步操作的同步化表达
ajax 请求,当请求到数据后要在这个异步函数中执行逻辑,使用 generator 函数可以将这执行逻辑取出来放在 ajax 下面。实现异步操作的同步化表达。 举个栗子
function* main(){
var result = yield request('' [http://some.url''](http://some.url'')) ;
var res = JSON.parse(result);
console.log(res.data);
}
function request(url){
makeAjaxCall(url, function(response){
it.next(response);
})
}
var it =main();
it.next();
代码分析:it.next()执行request('' http://some.url'') ; 执行 request 函数,得到结果 response,然后 next(response);将参数作为yield 语句的返回结果赋值给 res。这样就能打印出 res.data了。
2,控制流管理
实际运用中主要是为了解决ajax回调地狱,用 promise 函数的 then 也可以来解决,但是使用 generator 函数可以更直接的将依赖拆解开来。举个栗子:
step1(function (value1){
step2(value1, function(value2){
…
})
})
使用 promise
Promise.resolve(step1).then(step2).then(res=>{
…
})
使用 generator
function* longRunningTask(value1){
try{
var value2 = yield step1(value1);
var value3 = yield step1(value2);
}catch(e){
}
}
但是我们要创建一个函数来一次自动执行所有步骤:
function schedule(task){
var taskObj = task.next(task.value);
if(!taskObj.done){
task.value = taskObj.value
schedule(task)
}
}
网友评论