随着异步/等待构造的流行,对内部机制的兴趣也在增加。 在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%的折扣:
