关于JavaScript ES6中的生成器,以及为什么可以选择研究它们

随着异步/等待构造的流行,对内部机制的兴趣也在增加。 在Internet上翻遍后,很容易发现async / await是基于众所周知的Promise和Generators,而后者却鲜为人知和流行。



该材料(我们今天出版的翻译)专门针对发电机。 即,这里我们将讨论它们如何工作,以及它们如何与promise一起用于async / await构造的肠子中。 本文的作者说,出于实际应用的考虑,发电机不是必须要掌握的。 此外,他指出,他希望读者对承诺有所了解。

迭代器和生成器


在JavaScript中,从发布ES6标准开始,出现了一些新功能,旨在简化异步数据流和集合的工作。 迭代器和生成器属于这一类。

迭代器的显着特征是,它们提供了一种方法,可以一次访问一个收集项,同时允许您跟踪当前项的标识符。

function makeIterator(array) {  var nextIndex = 0;  console.log("nextIndex =>", nextIndex);  return {    next: function() {      return nextIndex < array.length        ? { value: array[nextIndex++], done: false }        : { done: true };    }  }; } var it = makeIterator(["simple", "iterator"]); console.log(it.next()); // {value: 'simple, done: false} console.log(it.next()); // {value: 'iterator, done: false} console.log(it.next()); // {done: true} 

上面,我们将makeIterator()函数传递给一个包含几个元素的小数组,然后我们使用一个迭代器遍历它,调用it.next()方法。 请注意说明使用迭代器获得的结果的注释。

现在让我们谈谈发电机。 生成器是像迭代器工厂一样工作的函数。 考虑一个简单的示例,然后讨论与生成器有关的两种机制。

 function* sample() { yield "simple"; yield "generator"; } var it = sample(); console.log(it.next()); // {value: 'simple, done: false} console.log(it.next()); // {value: 'generator, done: false} console.log(it.next()); // {value: undefined, done: true} 

注意函数声明中的星号。 这表明此函数是生成器。 另外,看看yield关键字。 它暂停函数的执行并返回某个值。 实际上,这两个功能是我们上面讨论的两种机制:

  • 生成器函数是 function关键字旁边或函数名称旁边使用星号声明的函数。
  • 生成器迭代器是在调用生成器函数时创建的。

通常,以上示例演示了生成迭代器的工厂函数的操作。

现在我们已经弄清楚了基础知识,让我们来谈谈更有趣的事情。 迭代器和生成器可以在两个方向上交换数据。 也就是说,生成器可以使用yield关键字将值返回给迭代器,但是迭代器也可以使用iterator.next('someValue')方法将数据发送给生成iterator.next('someValue') 。 这是它的外观。

 function* favBeer() { const reply = yield "What is your favorite type of beer?"; console.log(reply); if (reply !== "ipa") return "No soup for you!"; return "OK, soup."; } { const it = favBeer(); const q = it.next().value; //    console.log(q); const a = it.next("lager").value; //     console.log(a); } // What is your favorite beer? // lager // No soup for you! { const it = favBeer(); const q = it.next().value; //    console.log(q); const a = it.next("ipa").value; //     console.log(a); } // What is your favorite been? // ipa // OK, soup. 

发电机和承诺


现在我们可以讨论生成器和Promise如何构成async / await构造的基础。 想象一下,生成器将返回promise,而不是使用yield关键字返回一些值。 在这种情况下,生成器可以包装在一个函数中,该函数将等待promise解析,并通过.next()方法将promise的值返回给生成器,如前面的示例所示。 有一个流行的库co ,它执行此类操作。 看起来像这样:

 co(function* doStuff(){ var result - yield someAsyncMethod(); var another = yield anotherAsyncFunction(); }); 

总结


根据该材料的作者,JS开发人员仅需要了解生成器是如何工作的,才能了解async / await设计的内部结构的特征。 但是直接在您自己的代码中使用它们是不值得的。 生成器在JavaScript中引入了暂停功能并在开发人员认为必要时(如果需要)返回该功能的能力。 到目前为止,在使用JS函数时,我们希望它们在被调用时可以简单地从头到尾执行。 暂停它们的功能已经很新了,但是可以在async / await结构中方便地实现此功能。

当然,可以对此观点争论不休。 例如,支持生成器的一个参数是知道生成器的工作方式对于使用async / await调试代码很有用,因为生成器隐藏在此构造中。 但是,该材料的作者认为,尽管如此,这不是在本机代码中使用生成器。

亲爱的读者们! 您如何看待发电机? 也许您知道一些使用它们的选择,这些选择可以证明它们可以直接在JS项目的代码中使用?

皇家促销代码可在我们的虚拟服务器上享受10%的折扣:

Source: https://habr.com/ru/post/zh-CN417481/


All Articles