欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS之Generator(生成器)

程序员文章站 2024-02-21 11:55:24
...

这阵子因为要学习React Native,而RN必备的知识就是JS,所以开始学习起来了Js,在此声明写博客就是为了更好的学习,总结一些我学习过程中知识点,有不同意见的请尽情发表!

1. 概述

     Generator 顾名思义是生成器,那什么是生成器?官网给出的解释:使用 function* 语法和一个或多个 yield 表达式以创建一个函数即为生成器,当然它的返回值就是一个迭代器即生成器。下面我们看一个简单的实例:
function* gen(x){
  var y = yield x + 2;
  return y;
}

上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。其实整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用 yield 语句注明。Generator 函数的执行方法如下:

function* gen(x){

  var y = yield x + 2;

  return y;

}

var g = gen(1);

console.log(g.next());//返回 对象 {value : 3, done : false }

console.log(g.next());//返回 对象 {value : undefined, done : false }

如图:

JS之Generator(生成器)

 上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止,再次调用g的next的方法,内部指针指向下个yield语句。

换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,这个对象就是具有两个属性(done (done=false) 和 value (value=operand))的 IteratorResult 对象。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。这里说明了Generator 函数可以暂停执行和恢复执行,这是它能封装异步任务的根本原

2.迭代器委托

使用yield*可以实现迭代器之间的委托,语法 : yield*  迭代器

function* stringIter() {
    var str = "bobsyouruncle";
    var idx = 0;
    while(idx < str.length)
        yield str[idx++];
}
function* strIter() {
    yield "jo";
    yield* stringIter();
}

var si2 = strIter();

console.log(si2.next().value);
console.log(si2.next().value);
console.log(si2.next().value);
console.log(si2.next().value);
输出:

jo
b
o
b

上面的代码则 yield* 委托到 stringIter 生成器。

3.next传递参数

    还可以将参数传递给 next 并使用该参数修改生成器的状态,以创建更高级的生成器。 next 将成为之前执行的 yield 表达式的结果值。在下面的示例中,当你将值 100 传递给 next 方法时,会重置生成器的内部索引值。如下代码:

function* strIter2() {
    var str = "jobob";
    var idx = 0;
    while(idx < str.length) {
        var modify = yield str[idx++];
        if(modify == 100) {
            idx = 0;
        }
    }
 
}
 
var str2 =  strIter2();
 
console.log(str2.next().value);
console.log(str2.next().value);
console.log(str2.next().value);

console.log(str2.next(100).value);

输出:

j

o

b

j

上面的代码给next传递100,内部索引值会被重置为0.

4.throw

genrator还可以处理错误代码:

function* genthrow(x){

  try {

    var y = yield x + 2;

  } catch (e){ 

   console.log("genthrow--------->" + e);

  }

  return y;

}


var thro = genthrow(1);

thro.next();

thro.throw("出错了")

    上面代码的最后一行,Generator 函数体外,使用指针对象的 throw 方法抛出的错误,可以被函数体内的 try ... catch 代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。


参考一:阮一峰随笔
参考二:MSDN