简体   繁体   English

理解 Node.js 中的 promise

[英]Understanding promises in Node.js

From what I have understood there are three ways of calling asynchronous code:据我了解,调用异步代码的方式有以下三种:

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

I found the node-promise library but I don't get it.我找到了node-promise 库,但我不明白。

Could someone explain what promises are all about and why I should use it?有人可以解释一下承诺的全部内容以及我为什么要使用它吗?

Also, why was it removed from Node.js?另外,为什么它从 Node.js 中删除了?

Since this question still has many views (like mine) I wanted to point out that:由于这个问题仍然有很多观点(比如我的),我想指出:

  1. node-promise looks rather dead to me (last commit was about 1 year ago) and contains nearly no tests. node-promise对我来说看起来很死(上次提交是大约 1 年前)并且几乎不包含任何测试。
  2. The futures module looks very bloated to me and is badly documented (and I think that the naming conventions are just bad) futures模块对我来说看起来很臃肿并且记录很糟糕(我认为命名约定很糟糕)
  3. The best way to go seems to be the q framework , which is both active and well-documented.最好的方法似乎是q framework ,它既活跃又记录良好。

Promises in node.js promised to do some work and then had separate callbacks that would be executed for success and failure as well as handling timeouts. node.js 中的 Promise 承诺做一些工作,然后有单独的回调,这些回调将在成功和失败以及处理超时时执行。 Another way to think of promises in node.js was that they were emitters that could emit only two events: success and error.在 node.js 中考虑 promise 的另一种方式是,它们是只能发出两个事件的发射器:成功和错误。

The cool thing about promises is you can combine them into dependency chains (do Promise C only when Promise A and Promise B complete). Promise 很酷的一点是你可以将它们组合成依赖链(只有在 Promise APromise B 完成时才执行 Promise C)。

By removing them from the core node.js, it created possibility of building up modules with different implementations of promises that can sit on top of the core.通过从核心 node.js 中删除它们,它创造了构建具有不同承诺实现的模块的可能性,这些模块可以位于核心之上。 Some of these are node-promise and futures .其中一些是node-promisefutures

A promise is a "thing" which represents the "eventual" results of an operation so to speak.一个promise是一个“事物”,可以说是代表一个操作的“最终”结果。 The point to note here is that, it abstracts away the details of when something happens and allows you to focus on what should happen after that something happens.这里要注意的一点是,它抽象了某事发生的细节,并让您专注于某事发生应该发生的事情。 This will result in clean, maintainable code where instead of having a callback inside a callback inside a callback, your code will look somewhat like:这将产生干净、可维护的代码,而不是在回调内部的回调中包含回调,您的代码看起来有点像:

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

The promises' spec states that a promise's承诺的规范指出承诺的

then

method should return a new promise that is fulfilled when the given successHandler or the failureHandler callback is finished.方法应该返回一个新的promise,当给定的successHandler 或failureHandler 回调完成时该promise 完成。 This means that you can chain together promises when you have a set of asynchronous tasks that need to be performed and be assured that the sequencing of operations is guaranteed just as if you had used callbacks.这意味着当您有一组需要执行的异步任务时,您可以将 promise 链接在一起,并确保操作的顺序得到保证,就像您使用了回调一样。 So instead of passing a callback inside a callback inside a callback, the code with chained promises looks like:因此,不是在回调内部的回调中传递回调,而是具有链式承诺的代码如下所示:

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

To know more about promises and why they are super cool, checkout Domenic's blog : http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/要了解有关 Promise 的更多信息以及它们为何非常酷,请查看 Domenic 的博客: http : //domenic.me/2012/10/14/youre-missing-the-point-of-promises/

This new tutorial on Promises from the author of PouchDB is probably the best I've seen anywhere.这个来自PouchDB作者的关于 Promises 的新教程可能是我见过的最好的教程 It wisely covers the classic rookie mistakes showing you correct usage patterns and even a few anti-patterns that are still commonly used - even in other tutorials!!它明智地涵盖了经典的新手错误,向您展示了正确的使用模式,甚至一些仍然常用的反模式 - 即使在其他教程中!

Enjoy!享受!

PS I didn't answer some other parts of this question as they've been well covered by others. PS 我没有回答这个问题的其他一些部分,因为其他人已经很好地涵盖了这些部分。

Mike Taulty has a series of videos , each of them less than ten minutes long, describing how the WinJS Promise library works. Mike Taulty有一系列视频,每个视频都不到十分钟,描述了 WinJS Promise 库的工作原理。

These videos are quite informative, and Mike manages to show the power of the Promise API with a few well-chosen code examples.这些视频内容丰富,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
     });

The treatment of how exceptions are dealt with is particularly good.如何处理异常的处理特别好。

In spite of the WinJs references, this is a general interest video series, because the Promise API is broadly similar across its many implementations.尽管有 WinJs 参考,但这是一个普遍感兴趣的视频系列,因为 Promise API 在其许多实现中大致相似。

RSVP is a lightweight Promise implementation that passes the Promise/A+ test suite. RSVP是通过 Promise/A+ 测试套件的轻量级 Promise 实现。 I quite like the API, because it is similar in style to the WinJS interface.我非常喜欢 API,因为它在风格上与 WinJS 界面相似。

Update Apr-2014 2014 年 4 月更新

Incidentally, the WinJS library is now open source .顺便提一下,WinJS 库现在是开源的

Another advantage of promises is that error handling and exception throwing and catching is much better than trying to handle that with callbacks.承诺的另一个优点是错误处理和异常抛出和捕获比尝试用回调来处理要好得多。

The bluebird library implements promises and gives you great long stack traces, is very fast, and warns about uncaught errors. bluebird库实现了 promises 并为您提供了很长的堆栈跟踪,速度非常快,并对未捕获的错误发出警告。 It also is faster and uses less memory than the other promise libraries, according to http://bluebirdjs.com/docs/benchmarks.html根据http://bluebirdjs.com/docs/benchmarks.html ,它也比其他承诺库更快并且使用更少的内存

What exactly is a Promise ? Promise 究竟是什么?

A promise is simply an object which represents the result of an async operation.承诺只是一个表示异步操作结果的对象。 A promise can be in any of the following 3 states :承诺可以处于以下 3 种状态中的任何一种:

pending :: This is the initial state, means the promise is neither fulfilled nor rejected. pending :: 这是初始状态,意味着承诺既没有履行也没有被拒绝。

fulfilled :: This means the promise has been fulfilled, means the value represented by promise is ready to be used. Completed :: 表示promise已经完成,表示promise所代表的值已经可以使用了。

rejected :: This means the operations failed and hence can't fulfill the promise.被拒绝:: 这意味着操作失败,因此无法履行承诺。 Apart from the states, there are three important entities associated to promises which we really need to understand除了状态之外,还有三个与 promise 相关的重要实体,我们确实需要了解它们

  1. executor function :: executor function defines the async operation which needs to be performed and whose result is represented by the promise. executor function :: executor function 定义了需要执行的异步操作,其结果由promise 表示。 It starts execution as soon as the promise object is initialized.一旦 promise 对象被初始化,它就会开始执行。

  2. resolve :: resolve is a parameters passed to the executor function , and in case the executor runs successfully then this resolve is called passing the result. resolve::resolve 是传递给 executor 函数的参数,如果 executor 运行成功,则调用此 resolve 传递结果。

  3. reject :: reject is another parameter passed to the executor function , and it is used when the executor function fails. reject::reject 是传递给执行器函数的另一个参数,在执行器函数失败时使用。 The failure reason can be passed to the reject.失败原因可以传递给拒绝。

So whenever we create a promise object, we've to provide Executor, Resolve and Reject.所以每当我们创建一个 promise 对象时,我们必须提供 Executor、Resolve 和 Reject。

Reference :: Promises参考 ::承诺

I've been also looking into promises in node.js recently.我最近也在研究 node.js 中的 promise。 To date the when.js seems to be the way to go due to its speed and resource use, but the documentation on q.js gave me a lot better understanding.迄今为止,由于速度和资源使用, when.js似乎是要走的路,但是q.js上的文档让我有了更好的理解。 So use when.js but the q.js docs to understand the subject.所以使用 when.js 但使用 q.js 文档来理解这个主题。

From the q.js readme on github:来自 github 上的q.js自述文件:

If a function cannot return a value or throw an exception without blocking, it can return a promise instead.如果函数不能在不阻塞的情况下返回值或抛出异常,它可以返回一个承诺。 A promise is an object that represents the return value or the thrown exception that the function may eventually provide. promise 是一个对象,表示函数最终可能提供的返回值或抛出的异常。 A promise can also be used as a proxy for a remote object to overcome latency.承诺也可以用作远程对象的代理来克服延迟。

Promise object represents the completion or failure of an asynchronous operation. Promise 对象表示异步操作的完成或失败。

So in order to implement a promise, you need two parts:-所以为了实现一个承诺,你需要两个部分:-

1. Creating Promise: 1.创建承诺:

The promise constructor accepts a function called an executor that has 2 parameters resolve and reject. 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. Handling Promise: 2.处理承诺:

Promise object has 3 methods to handle promise objects:- Promise 对象有 3 种方法来处理 Promise 对象:-

1.Promise.prototype.catch(onRejected) 1.Promise.prototype.catch(onRejected)

2.Promise.prototype.then(onFullfiled) 2.Promise.prototype.then(onFullfiled)

3.Promise.prototype.finally(onFullfiled,onRejected) 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 })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM