了解Node.js中的承诺


147

据我了解,有三种调用异步代码的方法:

  1. 活动,例如 request.on("event", callback);
  2. 回调,例如 fs.open(path, flags, mode, callback);
  3. 承诺

我找到了节点承诺库,但是我不明白。

有人可以解释什么是诺言,为什么我要使用它?

另外,为什么将它从Node.js中删除?


本文对此进行了很好的解释。关于可在node.js中使用的实现,请看一下Futures
Sean Kinsey 2010年

这是我用来创建自己的Promise类的一个很棒的系列:让我们做一个框架:承诺这里是有关jQuery Deferred的视频:blog.bigbinary.com/2011/09/03/jquery-deferred.html
Tom Winter

Answers:


91

node.js中的承诺承诺会做一些工作,然后有单独的回调,将为成功和失败以及处理超时而执行。在node.js中考虑promise的另一种方式是,它们是可能仅发射两个事件的发射器:成功和错误。

关于promise的很酷的事情是您可以将它们组合到依赖关系链中(仅当Promise A Promise B完成时才执行Promise C )。

通过将它们从核心node.js中删除,它使构建具有可能位于核心之上的promises的不同实现的模块成为可能。其中一些是节点承诺期货


10
@weng不,不是。
伊沃·韦策尔

98

由于这个问题仍然有很多观点(例如我的观点),我想指出:

  1. node-promise对我来说似乎已经死了(上一次提交是在1年前),并且几乎没有测试。
  2. 期货模块看起来很臃肿的我,被严重记录(我认为的命名约定是有害的)
  3. 最好的方法似乎是q框架,该框架既活跃又有据可查。

9
还要检查这个github.com/medikoo/deferred,Q是第一个,它无疑是后来出现的许多实现的灵感,但是不幸的是,它非常缓慢,并且在某些部分过于“理论”,在某些方面它不能很好地发挥作用。现实世界中的场景
Mariusz Nowak

我想通过RSVP.js的创造者之一退房承诺这个视频 youtube.com/...
runspired

23
2014年更新- 蓝鸟是迄今为止最快和调试能力最强的一种。
Benjamin Gruenbaum 2014年

19

一个承诺是一个“事物”,它代表了操作的“最终”结果。这里要注意的一点是,它抽象掉的细节,当有事情发生,让您专注于应该发生什么说有事。这将产生干净,可维护的代码,其中的代码将类似于以下内容:

 var request = new Promise(function(resolve, reject) {
   //do an ajax call here. or a database request or whatever.
   //depending on its results, either call resolve(value) or reject(error)
   //where value is the thing which the operation's successful execution returns and
   //error is the thing which the operation's failure returns.
 });

 request.then(function successHandler(result) {
   //do something with the result
 }, function failureHandler(error) {
  //handle
 });

诺言的规范指出诺言的

then

方法应返回一个新的Promise,该Promise将在给定SuccessHandler或failureHandler回调完成时得到满足。这意味着当您有一组需要执行的异步任务时,您可以将promise链接在一起,并确保可以保证操作顺序就像使用回调一样。因此,带有链接的promise的代码不是在回调内部的回调内部传递回调,而是:

var doStuff = firstAsyncFunction(url) {
                return new Promise(function(resolve, reject) {
                       $.ajax({
                        url: url,
                        success: function(data) {
                            resolve(data);
                        },
                        error: function(err) {
                             reject(err); 
                        } 
                  });
               };
doStuff
  .then(secondAsyncFunction) //returns a promise
  .then(thirdAsyncFunction); //returns a promise

要了解有关承诺及其为何超酷的更多信息,请查看Domenic的博客:http : //domenic.me/2012/10/14/youre-missing-the-point-of-promises/


12

这种新的教程从笔者承诺PouchDB可能是我在任何地方见过的最好的。它明智地涵盖了经典的菜鸟错误,向您显示了正确的用法模式,甚至是一些仍常用的反模式-甚至在其他教程中也是如此!

请享用!

PS:我没有回答这个问题的其他部分,因为其他部分已经很好地覆盖了它们。


为此,我唯一的道歉是迫使您在高级错误#4结束时阅读幽默。
Tony O'Hagan

实际上,教程中声称自己是反模式的代码需要嵌套循环和条件,并且不能像他们建议的那样容易地扁平化。
Bergi 2015年

还可以使用大量其他方法来解决高级错误#4,请参阅如何在.then()链中访问先前的承诺结果?(他们建议的关闭模式似乎不太流行)。
Bergi 2015年

我认为这个仅链接的答案最好是评论。请至少在此处的答复中注明该文章的要点。
Bergi 2015年

7

Mike Taulty 拥有一系列视频,每个视频都不超过十分钟,描述了WinJS Promise库的工作原理。

这些视频内容丰富,Mike设法通过一些精选的代码示例来展示Promise API的功能。

var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });

 promise = promise.then(
     function (xhr) {
     },
     function (xhr) {
         // handle error
     });

处理异常的方式特别好。

尽管有WinJs的参考资料,但由于Promise API在其许多实现中大致相似,因此这是一个广受欢迎的视频系列。

RSVP是通过Promise / A +测试套件的轻量级Promise实现。我非常喜欢该API,因为它的样式类似于WinJS接口。

2014年4月更新

顺便说一下,WinJS库现在是开源的


1
+1。这是我见过的第一个对我来说有意义并且易于使用的示例。不知何故,我的大脑无法解析流行的Q库文档中的所有deferredsand resolvedeferred.promise.thenand预定义promiseActions。您是否有机会对Node.js这么简单的了解?
Redsandro

1
@noel感谢您分享上面的链接,这是一个很好的Promise入门系列,我同意WinJS的具体内容与整体方法/主题是通用的无关。
arcseldon 2014年

很好的例子。我也修复了您的第一个链接已死的问题
stonedauwg,2016年

5

promise的另一个优点是,错误处理以及引发和捕获异常的方法比尝试使用回调处理要好得多。

蓝鸟库实现承诺,并为您提供一流长的堆栈跟踪,速度非常快,并警告有关未被捕获的错误。根据http://bluebirdjs.com/docs/benchmarks.html的介绍,与其他Promise库相比,它还更快,使用的内存更少。


4

什么是诺言?

一个promise只是一个代表异步操作结果的对象。一个承诺可以处于以下三种状态中的任何一种:

待定 ::这是初始状态,表示未实现或拒绝承诺。

已实现 ::这表示已兑现承诺,表示可以使用承诺表示的值。

被拒绝 ::这意味着操作失败,因此无法兑现承诺。除州外,我们还需要了解与承诺相关的三个重要实体

  1. executor function :: executor function定义需要执行的异步操作,其结果由promise表示。一旦promise对象初始化,它将开始执行。

  2. resolve :: resolve是传递给executor函数的参数,如果执行程序成功运行,则调用此resolve传递结果。

  3. reject :: reject是传递给executor函数的另一个参数,在executor函数失败时使用。失败原因可以传递给拒绝项。

因此,每当我们创建一个Promise对象时,我们都必须提供Executor,Resolve和Reject。

参考:: 承诺


0

我最近也一直在研究node.js中的promises。迄今为止,由于它的速度和资源使用情况,when.js似乎是可行的方法,但是q.js上的文档使我有了更好的理解。因此,请使用when.js而非q.js文档来理解该主题。

来自github上的q.js自述文件:

如果一个函数不能返回值或抛出异常而不阻塞,则可以返回一个Promise。Promise是一个对象,代表该函数最终可能提供的返回值或引发的异常。Promise也可以用作远程对象的代理,以克服延迟。


0

Promise对象代表异步操作的完成或失败。

因此,要实现承诺,您需要两个部分:

1. 创造承诺:

promise构造函数接受一个名为executor的函数,该函数具有2个参数resolve和reject。

function example(){
   return new Promise (function(resolve , reject){   //return promise object
      if(success){
         resolve('success');  //onFullfiled
      }else{
         reject('error');     //onRejected
      }
   })
}

2。处理承诺:

Promise对象具有3种处理Promise对象的方法:-

1. Promise.prototype.catch(onRejected)

2.Promise.prototype.then(onFullfiled)

3.Promise.prototype.finally(onFullfiled,onRejected)

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.