61

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

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

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

因此,如果聪明的社区可以帮助回答并澄清与下面列出的技术有关的以下问题(粗体字),我会很高兴:

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

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

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

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

(希望作为答案一部分的意见可以得到很好的解释。)

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

技术:

*考阿*

我的理解:

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 相同的效用,如果是,那么到什么程度?

* 重击和承诺 *

我想我对它们是什么有一个公平的处理,但希望有人能提供一个简洁明了的“电梯间距”定义,当然,如上所述,解释何时使用一个与另一个 -在 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(?) 中使用。如果是这样,那么效果如何?

谢谢大家!

4

1 回答 1

55

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

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

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

发电机

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

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

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

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

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

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

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

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

公司

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

还有其他的生成器库,其中一些我能想到的就是挂起和生成运行。我已经尝试了所有这些,并且共同提供了最大的灵活性。如果您还不习惯生成器,那么暂停可能会更容易遵循,但我不能权威地这么说。

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

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

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

承诺

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

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

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

桑克斯

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

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

在我看来,Thunk 很容易理解和使用,但它们并不是适合所有事情的工具。例如 spawn 是创建 thunk 的主要痛苦,你可以做到但并不容易。

Thunks 与 Promise

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

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

何时使用

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

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

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

您可以将它们一起使用,只要您可以保留它,以便很明显哪个是您不会有问题的。

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

考阿

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

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

于 2014-04-16T08:13:04.167 回答