【问题标题】:Koa / Co / Bluebird or Q / Generators / Promises / Thunks interplay? (Node.js) [closed]Koa / Co / Bluebird 或 Q / Generators / Promises / Thunks 相互作用? (Node.js)[关闭]
【发布时间】:2014-05-30 18:14:28
【问题描述】:

我正在研究部分使用 Koa 构建一个 Web 应用程序,但我不太了解如何、何时以及为什么在支持性“使异步更容易”技术之间进行选择 - 和应用 - 范围/方法(如下所列)。

总体而言,网络上关于这个主题的不同指导仍然使事情变得模糊,特别是在不断发展的最佳实践,或者至少是更好的实践方面,以及在什么情况下。网络上似乎很少或根本没有将这一切放在上下文中。

我希望对这个庞大的帖子的回复可以纠正这一点。另外,也许下面的问题可以激发某人写一篇详尽的博客文章或类似的文章来解决这个问题。我的感觉是,我什至不是唯一能从中受益的人。

因此,如果聪明的社区能够帮助回答并明确以下与下列技术相关的问题(粗体字),我将非常高兴:

-- a) 它们如何以及在何种情况下(如适用)相互补充、补充、替代和/或重叠解决方案?

-- b) 在速度-性能、错误处理的便利性和调试的便利性方面,它们的权衡是什么?

-- c) 何时、何地以及为什么使用“这个”与“那个”技术、技术组合和/或方法相比更好?

-- d) 哪些技术或方法(如果有)可能是“暗星”。

(希望答案中的观点能得到很好的解释。)

================================

技术:

* Koa *

我的理解:

Koa 是构建 Node 应用程序的最小基础,旨在利用 ECMAScript-6 功能,其中一个功能特别是生成器。

* 合作 *

我的理解:

-- Co 是一个用于运行 ECMAScript-6 生成器的实用程序库(它是 Node .011 和谐的本机),旨在减轻一些/很多(?)需要编写样板代码来运行和管理发电机。

-- Co 本质上是 Koa(?) 的一部分。

具体问题:

-- 如果以及如何在 Koa 中与在非 Koa 上下文中不同地使用 Co。换句话说,Koa 是不是全副武装?

-- 如果有/曾经有更好的生成器库,是否可以将 Koa 中的 Co 替换为其他类似的生成器库?有吗?

* Promise 库,例如“Q”和 Bluebird *

我的理解:

-- 在某种意义上,它们是用于实现 Promises/A+ 规范的“polyfills”,如果且直到 Node 原生运行该规范。
-- 他们还有一些非规范的便利实用程序来促进使用承诺,例如 Bluebird 的 promisfyAll 实用程序。

具体问题:

-- 我的理解是 ECMAScript-6 规范确实/将在很大程度上反映 Promises/A+ 规范,但即便如此,Node 0.11v 和谐并没有原生实现 Promises。 (这是正确的吗?)但是,当它出现时,Q 和 Bluebird 等技术会被淘汰吗?

-- 我读过一些东西,大意是“Q”和 Bluebird 支持生成器。这是什么意思?这是否在一定程度上意味着,例如,它们在某种程度上提供了与 Co 相同的效用,如果可以,达到什么程度?

* Thunks 和 Promise *

我想我对它们是什么有一个公平的处理,但希望有人可以提供一个简洁明了的“电梯间距”定义,当然,如上所述,解释何时使用一个与其他——在 Koa 上下文中而不是在其中。

具体问题:

-- 使用 Bluebird 的 promisfy 与使用 Thunkify (github com/visionmedia/node-thunkify) 之类的东西的优缺点?

================================

为了给这篇文章及其问题提供更多背景信息,如果可以讨论和对比以下网页中介绍的 Koa 技术可能会很有趣(特别是在优缺点的基础上):

-- a) www.marcusoft 。 net/2014/03/koaintro.html(thunk 或 promises 在哪里,或者我什么都没看到?)

-- b) 强循环。 com/strongblog/node-js-express-introduction-koa-js-zone(同样,thunk 或 promises 在哪里?)

-- c) github 。 com/koajs/koa/blob/master/docs/guide.md(“下一个”参数等同于什么,以及它的设置和位置?)

-- d) blog.peterdecroos 。 com/blog/2014/01/22/javascript-generators-first-impressions (不在 Koa 上下文中,但展示了 Co 与 Promise 库(Bluebird)的使用,所以我假设这里介绍的技术/模式借给自己在 Koa 中使用(?)。如果是这样,那么效果如何?

谢谢大家!

【问题讨论】:

  • Bluebird promisify with Bluebird coroutine for generator 是迄今为止最快的方法。它还恰好提供了目前具有长堆栈跟踪的最佳可调试性选项。我会说这是一个不错的选择。
  • 另外,这就像一百万个问题。有些不错,有些过于基于意见。
  • Co 是 express 作者创建的用于轻松编写非阻塞代码的库。通常我们必须使用回调和异步函数,这会变得很难看。优雅地链接它们可能是一个挑战。在 express 中,服务器链接各种中间件。 Koa 就像 express 一样,是一个中间件。但它使用 co 来管理内部。问题是生成器很好,但它们是同步的。所以你需要承诺与他们合作。公司为你做这件事。
  • 这不是 QA 而是讨论。因此它适合论坛,而不适合 SO。
  • @Connor 聊天室不会留下可用信息来帮助未来的观众

标签: node.js generator promise bluebird koa


【解决方案1】:

一个月以来,我几乎一直在广泛地使用发电机,所以也许我可以尝试一下。我会尽量减少意见。希望它有助于澄清一些困惑。

缺乏最佳实践和更好解释的部分原因是该功能在 javascript 中仍然很新。仍然很少有地方可以使用生成器 node.js,而 firefox 是最突出的,尽管 firefox 与标准略有不同。

我想指出,有一些工具,如 traceur 和 regenerator,可以让你使用它们进行开发,并允许你将它们变成半等效的 ES5,所以如果你觉得使用它们很有趣,那么没有理由不开始除非您针对的是过时的浏览器,否则请使用它们。

发电机

生成器最初并没有被认为是处理异步控制流的一种方式,但它们在这方面工作得很好。生成器本质上是迭代器函数,允许通过使用 yield 暂停和恢复它们的执行。

yield 关键字本质上是说为这次迭代返回这个值,当你再次对我调用 next() 时,我会从上次中断的地方继续。

生成器函数是特殊函数,它们在第一次调用时不会执行,而是返回一个带有一些方法的迭代器对象,并且能够用于 for-of 循​​环和数组解析。

send(),: 这会将一个值发送到生成器中,将其视为 yield 的最后一个值并继续下一次迭代

next(),: 这会继续生成器的下一次迭代

throw():这会将异常抛出到生成器中,导致生成器抛出异常,就好像它来自最后一个 yield 语句一样。

close():这会强制生成器返回执行并调用生成器的任何 finally 代码,以便在需要时触发最终错误处理。

它们的暂停和恢复能力使它们在管理流控制方面如此强大。

合作

Co 是围绕生成器的能力而构建的,以使处理流控制更容易。它不支持你可以用生成器做的所有事情,但你可以通过它的使用来使用它们中的大部分,而减少样板和头痛。出于流量控制的目的,我还没有发现除了 co 已经提供的东西之外我还需要任何东西。虽然公平地说,我没有尝试在流量控制期间向生成器发送值,但这确实带来了一些有趣的可能性......

还有其他的生成器库,我能想到的其中一些是suspend 和gen-run。我已经尝试了所有这些,并且共同提供了最大的灵活性。如果您还不习惯生成器,那么暂停可能会更容易理解,但我不能凭权威这么说。

就节点和最佳实践而言,我想说 co 目前正在通过大量支持它而创建的支持工具赢得胜利。暂停最有可能获得亚军。

Co 同时使用 Promise 和 thunk,它们用于 yield 语句,以便 co 知道何时继续执行生成器,而不必手动调用 next()。 Co 还支持使用生成器、生成器函数、对象和数组来进一步支持流控制。

通过产生一个数组或一个对象,您可以对所有产生的项目共同执行并行操作。通过屈服于生成器或生成器函数,co 会将进一步的调用委托给新生成器,直到它完成,然后在当前生成器上继续调用 next,从而允许您使用最少的样板代码有效地创建非常有趣的流控制机制。

承诺

虽然我说过我会尽量减少意见,但我想说的是,对我来说,承诺可能是最难掌握的概念。它们是维护代码的强大工具,但很难掌握其内部工作原理,并且如果用于高级流程控制,可能会出现很多问题。

我能想到的解释 Promise 的最简单方法是,它们是由函数返回的对象,该对象维护函数的状态以及当对象的特定状态是或已经是时要调用的回调列表进入。

promise 库本身不会很快消失。他们为没有进入 ES6 规范的 done() 等承诺添加了很多优点。更不用说可以在浏览器和节点中使用相同的库这一事实,我们将拥有它们很长一段时间。

谢谢

Thunk 只是接受单个参数回调并返回它们正在包装的另一个函数的函数。

这会创建一个闭包,允许调用代码实例化传入其回调的函数,以便在方法完成时告知它。

在我看来,Thunk 相当容易理解和使用,但它们并不是适用于所有事情的正确工具。例如,spawn 是创建 thunk 的一大难题,您可以做到但并不容易。

Tunks 与 Promise

这些不是相互排斥的,可以很容易地一起使用,但通常最好选择一个并坚持下去。或者至少选择一个约定,以便您可以轻松分辨哪个是哪个。根据我的经验,Thunk 运行得更快,但我没有对其进行基准测试。这大部分可能是因为它是一个较小的抽象,并且没有内置错误处理机制。

您通常会构建一些需要错误处理的东西,但是根据您的代码,thunk 的整体性能提升很容易达到或偏向于 Promise。

何时使用

生成器 - 当您可以放心地说您的应用程序将能够在最前沿运行时,无论是仅用于浏览器或节点的 firefox > 0.11.3

我已经在我现在离开的公司广泛使用它们,并且对它们允许的控制流机制和惰性评估感到非常满意。

Promises vs. Thunks - 这完全取决于您以及您使用它们的舒适程度。它们没有提供相同的好处,也没有解决相同的问题。 Promise 有助于直接处理异步问题,thunk 只是确保一个函数接受其他代码传入所需的回调参数。

您可以同时使用它们,只要您可以保留它,以便清楚哪个是您不会有问题的。

Promises/Thunk with Generators - 我建议您在使用生成器进行控制流时这样做。这不是必需的,但它更容易,就像使用 co 作为生成器的控制流的抽象更容易一样。需要键入的代码更少,维护更容易,并且您遇到其他人尚未遇到的边缘情况的可能性也更少。

考阿

我不会详细介绍 koa。可以说这与 express 类似,但它是为了利用生成器而编写的。这确实给了它一些独特的优势,例如更容易的错误处理和级联中间件。以前有一些方法可以完成所有这些任务,但它们并不优雅,有时也不是最好的。

特别说明: 生成器打开了一扇我们还没有探索过的可能性之门。就像它们可以用于控制流一样,当这不是它们的初始设计时,我很肯定它们可以用于解决我们通常在 javascript 中遇到的许多其他问题。可能比我更聪明的人会发现我们还能如何使用它们,但我至少会开始玩弄它们并更好地了解它们的能力。 ES.next 中还有更多用于生成器的好东西。

【讨论】:

  • 对不起,这个答案还不错,看来你花了很多时间。虽然我重视目前的贡献,但我认为它在上下文中没有用。对于 OP 提出的过于具体的问题而言,它过于具体,并且“何时使用”部分非常基于意见。
  • promises 部分也非常缺乏,但这不是重点。此外,生成器多年来一直用于其他语言的异步流控制。C# 甚至通过 async/await 结构内置了它们,这也是 ES7 的一个工作提案。
  • 同意。当涉及到一些相对较新和尚未探索的东西时,很难让答案保持冷静。希望它至少能帮助减轻一些关于什么的困惑,即使不是关于时间和原因的那么多。
  • 虽然其他语言已经拥有生成器很长时间了,不仅是 C#,还有 python,javascript 域本身有很多奇怪之处,特别是在尚未探索它们的使用的浏览器端.就像任何其他语言结构一样,它们不是灵丹妙药,但它们确实让生活更轻松:)。
  • Thot,感谢您的回复。 .... Ben,同样感谢您的回复。我意识到我不清楚协程与生成器之间的区别是什么。我的感觉是,前者只是运行后者的控制逻辑,并提高过去的产量。也许我在这点上是对的,至少部分是对的,但我现在感觉到协程的概念与生成器不同且独立(?)。
猜你喜欢
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 2015-06-23
  • 1970-01-01
  • 2018-04-05
相关资源
最近更新 更多