【问题标题】:Understanding promises in Node.js理解 Node.js 中的 Promise
【发布时间】:2011-05-16 20:09:43
【问题描述】:

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

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

我找到了node-promise library,但我不明白。

有人能解释一下承诺的全部内容以及我为什么要使用它吗?

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

【问题讨论】:

标签: javascript node.js promise


【解决方案1】:

由于这个问题仍然有很多观点(就像我的一样),我想指出:

  1. node-promise 对我来说似乎已经死了(上一次提交大约是 1 年前)并且几乎不包含任何测试。
  2. futures 模块在我看来非常臃肿,而且文档也很糟糕(而且我认为命名约定很糟糕)
  3. 最好的方法似乎是q framework,它既活跃又有据可查。

【讨论】:

  • 还要检查这个github.com/medikoo/deferred,Q 是第一个,它绝对是后来出现的许多实现的灵感,但不幸的是它非常缓慢并且在某些部分过于“理论化”,它没有与一些现实世界的场景配合得很好
  • 我会观看此视频,了解 RSVP.js 的一位创建者的承诺youtube.com/…
  • 2014 年更新 - bluebird 是迄今为止最快的,也是当今调试能力最强的。
【解决方案2】:

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

promise 很酷的一点是你可以将它们组合成依赖链(只有在 Promise A Promise B 完成时才执行 Promise C)。

通过从核心 node.js 中删除它们,它创造了构建具有不同承诺实现的模块的可能性,这些承诺可以位于核心之上。其中一些是node-promisefutures

【讨论】:

    【解决方案3】:

    promise 是一个“事物”,可以说是一个操作的“最终”结果。这里要注意的一点是,它抽象出when某事发生的细节,并允许您专注于某事发生之后应该发生的事情。这将产生干净、可维护的代码,而不是在回调中的回调中包含回调,您的代码看起来有点像:

     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
     });
    

    promise 的规范声明一个promise 的

    then
    

    方法应该返回一个新的promise,当给定的successHandler 或failureHandler 回调完成时该promise 会被履行。这意味着当您有一组需要执行的异步任务时,您可以将 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
    

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

    【讨论】:

      【解决方案4】:

      这个new tutorial 来自PouchDB 的作者的Promises 可能是我在任何地方见过的最好的。它明智地涵盖了经典的菜鸟错误,向您展示了正确的使用模式,甚至还有一些仍然常用的反模式——即使在其他教程中也是如此!!

      享受吧!

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

      【讨论】:

      • 对此我唯一的道歉是强迫你在高级错误 #4 结尾处阅读幽默。
      • 事实上,教程中他们声称是反模式的代码需要循环和条件的嵌套,并且不能像他们建议的那样容易扁平化。
      • 高级错误 #4 也可以使用更多不同的方法来解决,请参阅 How do I access previous promise results in a .then() chain?(他们建议的 closure pattern 似乎不是很受欢迎)。
      • 我认为这个仅链接的答案最好是评论。请在此处的回答中至少填写那篇文章的要点。
      【解决方案5】:

      Mike Taulty has a series of videos,每个人都不到十分钟,描述了 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 实现,它通过了 Promise/A+ 测试套件。我很喜欢这个 API,因为它在风格上与 WinJS 界面相似。

      2014 年 4 月更新

      顺便提一下,WinJS 库is now open source

      【讨论】:

      • +1。这是我见过的第一个对我有意义的示例并且使用起来很直观。不知何故,我的大脑无法解析流行的 Q 库文档中的所有 deferredsresolvedeferred.promise.then 以及 promiseActions 的预定义。你有没有机会知道 Node.js 这么简单的东西?
      • @noel 感谢您分享上面的链接,这是一个优秀的 Promise 入门系列,我同意 WinJS 的细节无关紧要,因为整体方法/主题是通用的。
      • 很好的例子。我还修复了你的第一个死链接
      【解决方案6】:

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

      bluebird 库实现了 Promise 并为您提供了非常长的堆栈跟踪,速度非常快,并警告未捕获的错误。根据http://bluebirdjs.com/docs/benchmarks.html

      的说法,它也比其他 Promise 库更快且使用更少的内存

      【讨论】:

        【解决方案7】:

        Promise 到底是什么?

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

        pending ::这是初始状态,表示promise既没有被履行也没有被拒绝。

        fulfilled :: 这表示promise已经实现,表示promise所代表的值已经可以使用了。

        rejected :: 这意味着操作失败,因此无法履行承诺。 除了状态之外,我们确实需要了解三个与 Promise 相关的重要实体

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

        2. resolve::resolve 是传递给执行器函数的参数,如果执行器运行成功则称为传递结果。

        3. reject::reject 是传递给执行器函数的另一个参数,在执行器函数失败时使用。失败原因可以传递给reject。

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

        参考:: Promises

        【讨论】:

          【解决方案8】:

          我最近也在研究 node.js 中的 Promise。迄今为止,when.js 似乎是要走的路,因为它的速度和资源使用率很高,但q.js 上的文档让我有了更好的理解。所以使用 when.js 而不是 q.js 文档来理解这个主题。

          来自q.jsgithub 上的自述文件:

          如果函数不能返回值或抛出异常 阻塞,它可以返回一个承诺。 Promise 是一个对象 表示函数的返回值或抛出的异常 最终可能会提供。一个promise也可以用作一个代理 远程对象来克服延迟。

          【讨论】:

            【解决方案9】:

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

            所以为了实现一个promise,你需要两个部分:-

            1.创造承诺:

            promise 构造函数接受一个名为 executor 的函数,该函数具有 2 个参数解析和拒绝。

            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
            })
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-06-01
              • 1970-01-01
              • 1970-01-01
              • 2017-05-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多