只是想知道是否有人可以在处理异步事件的模块之间进行权衡比较。具体来说,我有兴趣了解使用Async而不是Fibers.promise的原因,至少现在我在测试代码中广泛使用了该方法。特别是,我在Fibers.promise中看到的主要优点之一是,我可以保持堆栈链的前端 fork ,从而可以使用try { } catch { } finally,并且还允许我确保在处理完请求后,响应结束。

有人在使用Q_oper8吗?我在另一页上找到了这个,只是想知道那是否已经死了,或者我应该检查一下。

最佳答案

我从未听说过Q_oper8,所以无法对此发表评论,但是我将从另一个方向对此进行评论。我首先听说了异步,然后听说了Fiber(及其辅助程序库),实际上,我不喜欢后者。

纤维的缺点

其他Javascript开发人员不熟悉

Fiber通过已编译的Fiber本机方法将共例程的概念引入Javascript,该方法继承了传递给它的Java脚本代码的解释,拦截对yield的调用以跳回到等待的协例。

这对您可能并不重要,但是如果您需要在团队中工作,则必须向您的成员讲授该概念(或者希望他们从其他语言(例如Go)中获得有关该概念的经验)。

没有Windows支持

因此,为了使用Fiber或在其之上编写的任何库,您必须首先针对其平台进行本机编译。我不使用Windows,但是请注意Windows不支持Fiber,因此会限制现成的库实用程序。这意味着您根本不会找到用Fiber编写的通用Node.js库(无论如何,您可能根本没有,因为它添加了一个昂贵的编译步骤,否则您会避免使用异步方法)。

浏览器不兼容

这意味着您使用Fiber编写的任何代码都将无法在浏览器中运行,因为您无法将本机代码与浏览器混合(我也不希望浏览器用户希望这样做),即使您编写的所有内容都是“Javascript ”(语法上是Javascript,但语义上不是)。

更困难的调试

尽管“回调 hell ”在视觉上可能不太令人满意,但是“连续传递样式”确实比Co-Routines有一件非常好的事情-您可以确切地知道调用堆栈中发生了问题的地方,并且可以向后追溯。协同例程在程序中的多个点上进入函数,并且可以从三种调用中退出:returnthrowyield(),后者也是返回点。

使用协同例程,您可以“同时”运行两个或多个函数之间的交叉执行,并且在事件循环上可能同时运行着多个协同例程。使用传统的回调,可以确保在执行该函数期间函数的外部范围是静态的,因此,仅在需要时检查这些外部变量一次。协同例程需要在每个yield()之后运行这些检查(因为它与原始协同例程的用法将转换为真实Javascript中的回调链)。

基本上,我认为使用协同例程的概念变得更加困难,因为它必须存在于Javascript事件循环内部,而不是作为一种实现方法。

是什么让Async变得“更好”?

越差越好

实际上,这是一种“更糟更好”的想法。 Async并不是扩展Javascript语言来尝试消除疣(在我看来,创建疣),而是一种纯Javascript解决方案来掩盖它们,例如化妆。

控制流明确

异步函数描述了需要跨越事件循环屏障的不同类型的逻辑流,并且该库涵盖了实现该逻辑所需的回调代码的实现细节,您只需提供它的功能即可大致按线性顺序运行它们将在整个事件循环中执行。

如果您愿意在异步方法的参数周围放下第一个缩进级别,则与Co-Routines相比,您没有多余的缩进,而function(callback) {声明中只有很少的额外行,如下所示:

var async = require('async');
var someArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
async.forEach(someArray,
function(number, callback) {
    //Do something with the number
    callback();
}, function(err) {
    //Done doing stuff, or one of the calls to the previous function returned an error I need to deal with
});

在这种情况下,您知道您的代码使用的所有变量只有在您的代码未更改的情况下才可以在运行代码之前进行更改,因此您可以更轻松地进行调试,并且只有一种“返回”机制:callback()您可以成功进行任何回调,也可以在出现问题时将回调传递给错误。

代码重用并不困难

上面的示例使代码重用变得困难,但这不是必须的。您始终可以将命名函数作为参数传递:
var async = require('async');

// Javascript doesn't care about declaration order within a scope,
// so order the declarations in a way that's most readable to you

async.forEach(someArray, frazzleNumber, doneFrazzling);

var someArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];

function frazzleNumber(number, callback) {
    // Do something to number
    callback();
}

function doneFrazzling(err) {
    // Do something or handle error
}

功能性,非强制性

异步模块不鼓励使用命令式流控制,并鼓励(需要跨越事件循环的部分)使用功能进行流控制。

函数样式的优点在于,您可以轻松地重用循环主体或条件主体,并且可以创建新的控制流“动词”,以更好地匹配代码流(由代码的存在证明)。异步库),例如async.auto控制流方法,该方法实现了函数调用顺序的依赖关系图解析。 (您指定了一系列命名函数,并列出了它要执行的其他函数(如果有的话),auto首先运行“独立”函数,然后运行下一个可以根据其相关函数完成运行的时间运行的函数。 )

而不是按照您的语言所规定的命令式风格来编写代码,而是按照问题的逻辑性来编写代码,并实现“胶合”控制流程以使其实现。

综上所述

Fiber具有扩展Javascript语言的本质,因此无法在Node.js中开发大型生态系统,尤其是当Async在外观部门占据80%的份额并且在Java协同例程中没有其他缺点的时候。

07-26 04:52