Generator-异步方案

  • Post author:
  • Post category:其他






简介

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

跟普通函数的区别



  • function


    关键字与函数名之间有一个星号;
  • 函数体内部使用


    yield


    表达式,定义不同的内部状态。


  • Generator


    函数不能跟new一起使用,会报错。

定义一个普通函数和定义一个Generator惰性函数

// 定义一个普通函数
function auto(){
    console.log('函数执行')
}
auto();//这是一个普通函数函数名字加上()执行函数内部的代码


// Generator函数的*号当前函数变懒了
function* auto(){//这种形式的函数叫做Generator函数
    //一遍情况下*是紧跟function关键词后面写的
    //加了*号让这个函数变懒了,即使加上函数名字启动依然没有执行内部的代码
    console.log('函数执行');
    console.log('函数执行');
    console.log('函数执行');
}		
var result = auto();


function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();



上面代码定义了一个 Generator 函数


helloWorldGenerator


,它内部有两个


yield


表达式(


hello





world


),即该函数有三个状态:


hello





world





return


语句(结束执行)。

调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象。

下一步,必须调用遍历器对象的

next

方法,使得指针移向下一个状态。也就是说,每次调用

next

方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个

yield

表达式(或

return

语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。

比如我们在控制台执行一遍

hw.next()

就会有以下的结果

ES6 没有规定,

function

关键字与函数名之间的星号,写在哪个位置。这导致下面的写法都能通过:

function * foo(x, y) { ··· }
function *foo(x, y) { ··· }
function* foo(x, y) { ··· }
function*foo(x, y) { ··· }





yield 表达式

由于 Generator 函数返回的遍历器对象,只有调用


next


方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。


yield


表达式就是暂停标志。


遍历器对象的

next

方法的运行逻辑如下:

1.遇到

yield

表达式,就暂停执行后面的操作,并将紧跟在

yield

后面的那个表达式的值,作为返回的对象的value属性值。


2.下一次调用

next

方法时,再继续往下执行,直到遇到下一个

yield

表达式。


3.如果没有再遇到新的

yield

表达式,就一直运行到函数结束,直到

return

语句为止,并将

return

语句后面的表达式的值,作为返回的对象的

value

属性值。


4.如果该函数没有

return

语句,则返回的对象的

value

属性值为

undefined




yield


表达式与


return


语句既有相似之处

都能返回紧跟在语句后面的那个表达式的值。


不同之处

每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。正常函数只能返回一个值,因为只能执行一次return;Generator 函数可以返回一系列的值,因为可以有任意多个yield。


注意:


yield

表达式只能用在 Generator 函数里面,用在其他地方都会报错。

另外,

yield

表达式如果用在另一个表达式之中,必须放在圆括号里面。

例如:

console.log('Hello' + yield 123); // SyntaxError
console.log('Hello' + (yield 123)); // OK





next 方法的参数


yield

表达式本身没有返回值,或者说总是返回

undefined



next

方法可以带一个参数,该参数就会被当作上一个

yield

表达式的返回值。

function* f() {
  for(var i = 0; true; i++) {
    var reset = yield i;
    if(reset) { i = -1; }
  }
}

var g = f();

g.next() // { value: 0, done: false }
g.next() // { value: 1, done: false }
g.next(true) // { value: 0, done: false }

大概就理解到这里了~



版权声明:本文为Lemontree_fu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。