JavaScript 中的 Deferred、Promise 和 Future 之间有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6801283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:14:51  来源:igfitidea点击:

What are the differences between Deferred, Promise and Future in JavaScript?

javascriptpromisefuturedeferred

提问by Tower

What are the differences between Deferreds, Promises and Futures?
Is there a generally approved theory behind all these three?

Deferreds、Promises 和 Futures 之间有什么区别?
这三者背后是否有普遍认可的理论?

采纳答案by fncomp

In light of apparent dislike for how I've attempted to answer the OP's question. The literal answer is, a promise is something shared w/ other objects, while a deferred should be kept private. Primarily, a deferred (which generally extends Promise) can resolve itself, while a promise might not be able to do so.

鉴于我显然不喜欢我试图回答 OP 的问题。字面的答案是,promise 是与其他对象共享的东西,而 deferred 应该保密。首先,延迟(通常扩展 Promise)可以自行解决,而 Promise 可能无法这样做。

If you're interested in the minutiae, then examine Promises/A+.

如果您对细节感兴趣,请查看Promises/A+



So far as I'm aware, the overarching purpose is to improve clarity and loosen coupling through a standardized interface. See suggested readingfrom @jfriend00:

据我所知,首要目的是通过标准化接口提高清晰度和松散耦合。请参阅@jfriend00 的建议阅读

Rather than directly passing callbacks to functions, something which can lead to tightly coupled interfaces, using promises allows one to separate concerns for code that is synchronous or asynchronous.

不是直接将回调传递给函数,这会导致紧密耦合的接口,使用 Promise 允许人们分离同步或异步代码的关注点。

Personally, I've found deferred especially useful when dealing with e.g. templates that are populated by asynchronous requests, loading scripts that have networks of dependencies, and providing user feedback to form data in a non-blocking manner.

就我个人而言,我发现 deferred 在处理例如由异步请求填充的模板、加载具有依赖关系网络的脚本以及以非阻塞方式提供用户反馈以形成数据时特别有用。

Indeed, compare the pure callback form of doing something after loading CodeMirror in JS mode asynchronously (apologies, I've not used jQuery in a while):

确实,比较一下在 JS 模式下异步加载 CodeMirror 之后做某事的纯回调形式(抱歉,我已经有一段时间没有使用 jQuery 了):

/* assume getScript has signature like: function (path, callback, context) 
   and listens to onload && onreadystatechange */
$(function () {
   getScript('path/to/CodeMirror', getJSMode);

   // onreadystate is not reliable for callback args.
   function getJSMode() {
       getScript('path/to/CodeMirror/mode/javascript/javascript.js', 
           ourAwesomeScript);
   };

   function ourAwesomeScript() {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   };
});

To the promises formulated version (again, apologies, I'm not up to date on jQuery):

对于承诺制定的版本(再次道歉,我不是最新的 jQuery):

/* Assume getScript returns a promise object */
$(function () {
   $.when(
       getScript('path/to/CodeMirror'),
       getScript('path/to/CodeMirror/mode/javascript/javascript.js')
   ).then(function () {
       console.log("CodeMirror is awesome, but I'm too impatient.");
   });
});

Apologies for the semi-pseudo code, but I hope it makes the core idea somewhat clear. Basically, by returning a standardized promise, you can pass the promise around, thus allowing for more clear grouping.

为半伪代码道歉,但我希望它使核心思想有些清晰。基本上,通过返回标准化的承诺,您可以传递承诺,从而允许更清晰的分组。

回答by Woahdae

These answers, including the selected answer, are good for introducing promises conceptually, but lacking in specifics of what exactly the differences are in the terminology that arises when using libraries implementing them (and there areimportant differences).

这些答案,包括所选择的答案,是良好的概念引入的承诺,但在细节缺乏究竟差别在使用图书馆实现它们(还有时出现的术语 重要的区别)。

Since it is still an evolving spec, the answer currently comes from attempting to survey both references (like wikipedia) and implementations (like jQuery):

由于它仍然是一个不断发展的规范,因此目前的答案来自尝试调查参考资料(如wikipedia)和实现(如jQuery):

  • Deferred: Never described in popular references, 1234but commonly used by implementations as the arbiter of promise resolution (implementing resolveand reject). 567

    Sometimes deferreds are also promises (implementing then), 56other times it's seen as more pure to have the Deferred only capable of resolution, and forcing the user to access the promise for using then. 7

  • Promise: The most all-encompasing word for the strategy under discussion.

    A proxy object storing the result of a target function whose synchronicity we would like to abstract, plus exposing a thenfunction accepting another target function and returning a new promise. 2

    Example from CommonJS:

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44
    

     

    Always described in popular references, although never specified as to whose responsibility resolution falls to. 1234

    Always present in popular implementations, and never given resolution abilites. 567

  • Future: a seemingly deprecated term found in some popular references 1and at least one popular implementation, 8but seemingly being phased out of discussion in preference for the term 'promise' 3and not always mentioned in popular introductions to the topic. 9

    However, at least one library uses the term generically for abstracting synchronicity and error handling, while not providing thenfunctionality. 10It's unclear if avoiding the term 'promise' was intentional, but probably a good choice since promises are built around 'thenables.' 2

  • Deferred:从未在流行参考文献1 2 3 4 中描述, 但通常被实现用作承诺解析(实现和)的仲裁者。 5 6 7resolvereject

    有时 deferred 也是承诺(实现then), 5 6其他时候,让 Deferred 只能够解析并强制用户访问使用承诺被认为更纯粹。 7then

  • 承诺:所讨论的战略最全面的词。

    一个代理对象,存储我们想要抽象其同步性的目标函数的结果,并暴露一个then接受另一个目标函数并返回一个新承诺的函数。 2

    来自CommonJS 的示例:

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44
    

     

    总是在流行的参考文献中描述,尽管从未指定谁的责任解决方案。 1 2 3 4

    始终出现在流行的实现中,并且从未给出解析能力。 5 6 7

  • 未来:在一些流行的参考文献1和至少一个流行的实现中 发现的看似已弃用的术语 8,但似乎已逐步退出讨论,而倾向于使用术语“承诺” 3,并且在该主题的流行介绍中并不总是提到。 9

    然而,至少有一个库使用这个术语来概括同步性和错误处理,但不提供then功能。 10目前尚不清楚避免使用“承诺”一词是否是有意的,但可能是一个不错的选择,因为承诺是围绕“thenables”构建的。 2

References

参考

  1. Wikipedia on Promises & Futures
  2. Promises/A+ spec
  3. DOM Standard on Promises
  4. DOM Standard Promises Spec WIP
  5. DOJO Toolkit Deferreds
  6. jQuery Deferreds
  7. Q
  8. FutureJS
  9. Functional Javascript section on Promises
  10. Futures in AngularJS Integration Testing
  1. 关于承诺和期货的维基百科
  2. 承诺/A+规范
  3. 关于 Promise 的 DOM 标准
  4. DOM 标准承诺规范 WIP
  5. DOJO 工具包延期
  6. jQuery 延迟
  7. FutureJS
  8. 关于 Promises 的功能性 Javascript 部分
  9. AngularJS 集成测试中的未来

Misc potentially confusing things

杂项可能令人困惑的事情

回答by Camilo Martin

What really made it all click for me was this presentationby Domenic Denicola.

真正让我大吃一惊的是 Domenic Denicola 的这个演讲

In a github gist, he gave the description I like most, it's very concise:

在一个github gist中,他给出了我最喜欢的描述,非常简洁:

The point of promises is to give us back functional composition and error bubbling in the async world.

promises 的重点是让我们返回异步世界中的函数组合和错误冒泡。

In other word, promises are a way that lets us write asynchronouscode that is almost as easy to write as if it was synchronous.

换句话说,承诺是一种方式,让我们编写异步代码,几乎是一样容易写,如果它是同步的

Consider this example, with promises:

考虑这个带有承诺的例子:

getTweetsFor("domenic") // promise-returning async function
    .then(function (tweets) {
        var shortUrls = parseTweetsForUrls(tweets);
        var mostRecentShortUrl = shortUrls[0];
        return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
    })
    .then(doHttpRequest) // promise-returning async function
    .then(
        function (responseBody) {
            console.log("Most recent link text:", responseBody);
        },
        function (error) {
            console.error("Error with the twitterverse:", error);
        }
    );

It works as if you were writing this synchronous code:

它就像您正在编写此同步代码一样工作:

try {
    var tweets = getTweetsFor("domenic"); // blocking
    var shortUrls = parseTweetsForUrls(tweets);
    var mostRecentShortUrl = shortUrls[0];
    var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
    console.log("Most recent link text:", responseBody);
} catch (error) {
    console.error("Error with the twitterverse: ", error);
}

(If this still sounds complicated, watch that presentation!)

(如果这听起来仍然很复杂,请观看该演示文稿!)

Regarding Deferred, it's a way to .resolve()or .reject()promises. In the Promises/Bspec, it is called .defer(). In jQuery, it's $.Deferred().

关于 Deferred,它是一种方式.resolve().reject()承诺。在Promises/B规范中,它被称为.defer(). 在 jQuery 中,它是$.Deferred().

Please note that, as far as I know, the Promise implementation in jQuery is broken (see that gist), at least as of jQuery 1.8.2.
It supposedly implements Promises/A thenables, but you don't get the correct error handling you should, in the sense that the whole "async try/catch" functionality won't work. Which is a pity, because having a "try/catch" with async code is utterly cool.

请注意,据我所知,jQuery 中的 Promise 实现已损坏(请参阅该要点),至少从 jQuery 1.8.2 开始。
它应该实现Promises/A thenables,但是您没有得到正确的错误处理,因为整个“异步 try/catch”功能将不起作用。这很遗憾,因为使用异步代码进行“try/catch”非常酷。

If you are going to use Promises (you should try them out with your own code!), use Kris Kowal's Q. The jQuery version is just some callback aggregator for writing cleaner jQuery code, but misses the point.

如果你打算使用 Promises(你应该用你自己的代码尝试它们!),使用Kris Kowal 的 Q。jQuery 版本只是一些回调聚合器,用于编写更清晰的 jQuery 代码,但没有抓住重点。

Regarding Future, I have no idea, I haven't seen that in any API.

关于 Future,我不知道,我还没有在任何 API 中看到过。

Edit:Domenic Denicola's youtube talk on Promisesfrom @Farm's comment below.

编辑:多梅尼克·丹尼科拉 (Domenic Denicola) 在 youtube 上关于承诺的谈话来自@Farm下面的评论。

A quote from Michael Hymanson (yes, Michael Hymanson) from the video:

从视频中引用迈克尔·Hyman逊(是的,迈克尔·Hyman逊):

I want you to burn this phrase in your mind: A promise is an asynchronous value.

我想让你把这句话铭记在心: A promise is an asynchronous value

This is an excellent description: a promise is like a variable from the future - a first-class reference to something that, at some point, will exist (or happen).

这是一个很好的描述:promise 就像来自未来的变量 - 对在某些时候将存在(或发生)的事物的一流引用。

回答by IRSHAD

A Promiserepresents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise of having a value at some point in the future.

一个承诺代表某个值的代理创建承诺时未必知道。它允许您将处理程序与异步操作的最终成功值或失败原因相关联。这让异步方法可以像同步方法一样返回值:异步方法返回的不是最终值,而是在未来某个时间点具有值的承诺。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

The deferred.promise()method allows an asynchronous function to prevent other code from interfering with the progress or status of its internal request. The Promise exposes only the Deferred methods needed to attach additional handlers or determine the state (then, done, fail, always, pipe, progress, state and promise), but not ones that change the state (resolve, reject, notify, resolveWith, rejectWith, and notifyWith).

deferred.promise()方法允许异步函数防止其他代码干扰其内部请求的进度或状态。Promise 仅公开附加处理程序或确定状态(then、done、fail、always、pipe、progress、state 和 promise)所需的 Deferred 方法,而不公开更改状态的方法(resolve、reject、notify、resolveWith、 rejectWith 和 notifyWith)。

If target is provided, deferred.promise()will attach the methods onto it and then return this object rather than create a new one. This can be useful to attach the Promise behavior to an object that already exists.

如果提供了目标,deferred.promise()则将方法附加到其上,然后返回此对象而不是创建一个新对象。这对于将 Promise 行为附加到已经存在的对象很有用。

If you are creating a Deferred, keep a reference to the Deferred so that it can be resolved or rejected at some point. Return only the Promise object via deferred.promise() so other code can register callbacks or inspect the current state.

如果您正在创建一个 Deferred,请保留对 Deferred 的引用,以便在某个时候可以解决或拒绝它。通过 deferred.promise() 仅返回 Promise 对象,以便其他代码可以注册回调或检查当前状态。

Simply we can say that a Promiserepresents a value that is not yet known where as a Deferredrepresents work that is not yet finished.

简单地说,一个Promise代表一个未知的值,而一个Deferred代表尚未完成的工作。



enter image description here

在此处输入图片说明

回答by mattLummus

  • A promiserepresents a value that is not yet known
  • A deferredrepresents work that is not yet finished
  • Apromise代表一个未知的值
  • Adeferred代表尚未完成的工作

A promise is a placeholder for a result which is initially unknown while a deferred represents the computation that results in the value.

promise 是最初未知的结果的占位符,而 deferred 表示产生该值的计算。

Reference

参考