Node.js控制流程:回调还是承诺?

时间:2012-02-22 08:28:46

标签: node.js control-flow

我知道node.js有很多control flow libraries。其中一些让一个链异步函数与回调(如async,asyncblock等),其他使用promise concept(Q,延期,期货等)。鉴于长时间运行的脚本会一个接一个地执行一系列可能随时失败的操作,您更喜欢哪种控制流程?为什么?有什么优点和缺点?

3 个答案:

答案 0 :(得分:13)

回调的优点:

  • 简单了解和创造。
  • 有点效率更高,因为创建的对象越少,垃圾回收越多。
  • Node始终选择(error,result)个回调。我建议遵循他们的参数顺序以保持一致性(而不是说(result1, result2, result3, error)。)

承诺的优点:

  • 提供流畅的界面,有时可以帮助缓解嵌套的回调地狱,如shown here。代码似乎通过链接.then(foo).then(bar)调用线性流动。
  • 一个好的promises库可以让你在 parallel 中运行许多异步操作,并且只有在它们全部完成时才会继续。 Deferred库通过map无缝地执行此操作,Q具有allResolved,ES6承诺提供Promise.all()。 (这也可以通过回调来实现,例如使用async.parallel(),但不是内置的。)
  • 一个好的promises库将允许您指定一个错误处理函数,如果任何排队函数失败,将会调用该函数。要使用回调执行此操作,需要在每次回调开始时使用一些样板:if (err) return callback(err);

对于将每秒运行多次的代码,在堆栈底部附近使用回调是有意义的。堆栈越高,承诺可能更好,因为它们更容易阅读和理解,并且可以更优雅地处理错误。

值得注意的是, promises可以在运行时从回调构建。因此,您可以在极简主义回调表单中实现核心代码,并且如果您愿意,仍然会公开该库的promises版本。 (如Q.nfbind()中所述。)

我很想知道其他优点/缺点。

  

额外提示:始终处理错误!使用这两种方法,如果您不处理错误,那么它就会消失,让您不知道为什么您的代码无法按预期工作。< / p>      

回调应该始终处理if (err) ...,如果Promise没有返回,则Promise应该始终有.catch()

     

即使您有时会遇到错误,也不需要处理错误,但不处理意外错误意味着如果将来更改代码,您将不会听到开发人员错误(如拼写错误)中的错误。

     

Promise .catch()的替代方法是收听unhandled rejections。就个人而言,我用它来发出.catch()缺失的警告!

答案 1 :(得分:5)

我认为没有太多客观的利弊。异步很受欢迎(基于npm packages that depend on it)。

我喜欢控制流库(特别是异步),因为我更容易理解。承诺使我感到困惑,而异步很容易理解。我怀疑它只是一个学习曲线的东西,如果我花了很多钱去学习它们,那么承诺会更具可读性。但我是否应该期待人们试图阅读我的代码呢?

还有第3种类型 - Fibers。光纤在Windows上不起作用,但(IMO)为应该串行执行的事物提供了最清晰的语法。

答案 2 :(得分:0)

我一直在尝试使用这个库的声明式方法:http://chainsjs.org还有更多的工作要做,但它让你能够定义一个“执行图”,你可以完全控制它来自简单映射的执行流程。