Node.js 承诺、异步或只是回调

Posted

技术标签:

【中文标题】Node.js 承诺、异步或只是回调【英文标题】:Node.js promises, async, or just callbacks 【发布时间】:2014-09-27 19:51:52 【问题描述】:

您能否向初学者解释一下“promise”、“async”和“callbacks”之间的区别。这些术语如何相互关联?这些是一样的吗?不同的东西?我什么时候用哪个?

【问题讨论】:

你应该使用哪一个是基于意见的。其他问题已经单独提出:***.com/questions/824234/what-is-a-callback-function - ***.com/questions/6801283/…。至于异步库与 Promises 相比,Promises 更强大且可组合,但这又是 我的 意见。 在我的意见中,你应该先学习 javascript 并发模型(也就是说,除了 API 给你的“主机函数”之外,所有东西都是同步的) . cps works in JavaScript 以及更普遍的函数如何接受函数参数,最后才是——promise 是如何工作的(它们不是魔法 :))。只有当你了解了这些东西时,我才会使用 Promise,在我的 opinion 中,它们是回调的更好替代方案,因为它们可以更好地处理错误并更好地组合。 这是一个有效的问题,并非基于意见。这些术语是高度相关的,对不同的术语进行澄清是适当的。请重新打开。 @MichaelAaronSafyan 在编辑之前是基于意见的,在编辑之后它与***.com/questions/4296505/… 非常接近。 根据我的经验,大多数事情都可以通过使用 Promise 来实现,而且它可以清楚地理解流程。使用 Promise 的缺点是,使用 Promise 的项目倾向于在任何地方使用它们,这有时会导致需要包装不使用它们的模块。异步可以很容易地与大量使用 CB 相结合,因此在长流程的情况下,它可以提供更好的结构。但是正如@Benjamin Gruenbaum 提到的,在继续之前,您应该先了解 JS 并发模型。 【参考方案1】:

异步是启动计算并提供函数或注册处理程序的通用设计模式,该处理程序最终将在计算完成后被调用(而不是在开始之前阻塞并等待计算完成)额外的工作)。如果没有异步,同时启动多个计算需要使用线程。

“回调”是指您提供给异步计算的函数,该函数将在计算完成时被调用。它被称为“回调”,因为它被异步函数调用,并且在被调用时,它将控制流返回到您可以控制的代码中。

“Promise”是一个特定的 JavaScript 原型和相关框架,它为以异步样式编写的代码带来一致性。 Promise 表示可能已完成或未完成(成功或不成功)的异步计算,并提供了一种对结果进行操作或处理错误的方法,而不管异步计算的完成状态如何。 Promise API 还提供用于组合多个异步计算的输出的实用程序(例如在下一次计算之前等待一组异步计算中的一个或全部完成)。

举一个没有 Promise 的简单例子:

var addThen = function(a, b, handler) 
  var result = a + b;
  handler(result);
;

// ...
addThen(2, 3, console.log);  // prints 5
// ...

和 Promise 的等价物:

var add = function(a, b) 
  return Promise.resolve(a + b);
;

// ...
add(2, 3).then(console.log); // prints 5
// ...

异步代码可以使用 Promise 也可以不使用,但使用 Promise 的主要优点是一致性(例如,成功回调和失败回调在参数列表中的位置,是否支持失败回调等)并支持可以将它们组合在一起的库。

【讨论】:

这是一本值得一读的关于 Promise 的文章:domenic.me/2012/10/14/youre-missing-the-point-of-promises 回调不一定是异步的,它是关于控制反转的——它可以作为命令或计算策略。例如,在[1, 2, 3, 4, 5, 0, 4].map(Boolean) 中没有任何异步发生,但函数Boolean 函数函数作为回调传递。这实际上是关于控制反转。 Promise 不是 JavaScript 原型,也不是框架,它们是由 Mark Miller 和 Barbara Liskov 等人在 JavaScript 还没有出现之前开创的概念。 添加,我不会将“异步”称为设计模式 - 模式是 CPS。此外,没有它你不需要线程来执行并发(一个很好的反例是协程)。通过回调的 JavaScript 并发本身就是并发,多个计算同时发生的事实是因为宿主对象而不是 JavaScript(在 ES6 之前根本没有并发的概念)。 所有这些都是优秀的 cmets。就像“并行”与“并发”一样,它实际上取决于我们尝试使用语言的精确程度以及重点是否在于代码的结构或执行顺序。不过,您是对的,async 确实假设存在一些延迟(例如,由于网络原因),而我提供的虚拟示例立即提供了结果。 CPS 可用于立竿见影的效果,但在异步环境中更有用且更受欢迎。 现在浏览器中已经有了 Promise 的具体实现,虽然你说得对,在此之前它有各种不同的化身。鉴于标签“JavaScript”和“Node.js”,我认为可以合理地假设这是 OP 的想法,而不是 Promise/Future/whatever 的一般模式。我还应该指出,协程基本上是轻量级的用户空间线程,但它们基本上是一回事。对于 OP 的知识水平,我认为区分没有帮助。

以上是关于Node.js 承诺、异步或只是回调的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 承诺和异步异常

Node.js 回调函数

Node.js学习四 Node.js回调函数

node js 回调函数

Node.js 回调函数

Node.js 回调函数