ES6中Generator的应用

Generator

介绍

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同,Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

Generator函数有两个特征:

  1. function关键字与函数名之间有个星号;

  2. 函数内部使用yield表达式

function* helloWorldGenerator() { 
	yield 'hello'; 
	yield 'world'; 
	return 'ending'; 
}
//如上代码有三个状态, 'hello'、'world'、'ending'

执行

Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个迭代器对象,调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。

let 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是实现状态机的最佳结构。

let flag = true;
function clock(){    
	if(flag){ console.log("tick");} else { console.log("tock"); }    
	flag = !flag;
}
function *  clock_generator(){    
  while(true){        
  console.log("tick"); yield;       
	console.log("tock"); yield;    
  }
}
clock();//tick滴
clock();//tock答
var cg=clock_generator();
cg.next();//tick {value:undefined,done:false}
cg.next();//tock {value:undefined,done:false}

案例:长轮询

// 定义一个generator函数,其返回值是一个promise
let ajax = function* () {
    yield new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({
                code: 0
            })
        }, 1000);
    })
}


// 定义一个轮询函数,当轮询结果的code!=0时,1秒之后开始下一次轮询
let pull = function () {
    let generator = ajax();
    let step = generator.next();
    step.value.then((v) => {
        if (v.code != 0) {
            setTimeout(() => {
                console.log('wait');
                pull();
            }, 1000);
        } else {
            console.log(v);
        }
    })
}


pull(); // 执行

案例:抽奖

// 抽奖处理
let draw = function (count) {
    // 此处省略具体的抽奖逻辑
    console.log(`剩余${count}次`);
}


// 根据剩余次数判断是否执行抽奖处理
let residue = function* (count) {
    while (count > 0) {
        count--;
        yield draw(count);
    }
}


// 初始化抽奖次数为5次
let star = residue(5);


// 创建抽奖按钮
let btn = document.createElement('button');
btn.id = 'start';
btn.textContent = '抽奖';
document.body.appendChild(btn);


// 绑定抽奖事件
document.getElementById('start').addEventListener('click', () => {
    star.next();
}, false)

异步操作的同步化。可以把异步操作写在yield表达式里面,等到调用next方法时再往后执行。这实际上等同于不需要写回调函数了,因为异步操作的后续操作可以放在yield表达式下面,反正要等到调用next方法时再执行。所以,Generator 函数的一个重要实际意义就是用来处理异步操作,改写回调函数。

function* main() {  
	let result = yield request("http://some.url");  
    let resp = JSON.parse(result);    
	console.log(resp.value);
}
function request(url) {  
	// response参数会当做上一个yield表达式的返回值
	axios.get(url).then(function(response){it.next(response);});
}
it = main();
it.next();




  
  
  Generator函数
  
  



你可能感兴趣的:(ES6,javascript,javascript,前端,es6)