JavaScript 中的 Deferred、Promise 和 Future 有什么区别?
延期、承诺和期货之间有什么区别?
这三个背后是否有一个普遍认可的理论?
What are the differences between Deferreds, Promises and Futures?
Is there a generally approved theory behind all these three?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这些答案,包括选定的答案,有利于引入承诺
从概念上讲,但缺乏具体差异的具体内容
使用库实现它们时出现的术语(并且有
是重要的区别)。
由于它仍然是不断发展的规范,目前的答案来自于尝试调查这两个参考文献(如 wikipedia)和实现(如 jQuery):
延迟:流行参考文献中从未描述过,
1
2
3
4
但通常被实现用作 Promise 解析的仲裁者(实现
resolve
和reject
)。5
6
7
有时延迟也是承诺(实现
then
),5
6
其他时候,仅使用 Deferred 被认为更纯粹
能够解决,并迫使用户访问承诺
使用
then
。7
承诺:对于正在讨论的策略来说,最包罗万象的词。
存储目标函数结果的代理对象,其
我们想要抽象同步性,并公开一个
then
函数接受另一个目标函数并返回一个新的承诺。
2
来自 CommonJS 的示例:
<前><代码>> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(打印结果);
44
尽管从未具体说明,但始终在流行参考文献中进行描述
责任决议落在谁的身上。
1
2
3
4
始终出现在流行的实现中,并且从未给出
分辨率能力。
5
6
7
未来:一些流行参考文献中看似已弃用的术语
1
以及至少一种流行的实现,
8
但似乎已逐渐退出讨论,转而使用该术语
'承诺'
3
并且在该主题的流行介绍中并不总是提及。
9
但是,至少有一个库通用地使用该术语来进行抽象
同步性和错误处理,但不提供
then
功能。10
目前尚不清楚回避“承诺”一词是否是有意为之,但可能是
这是一个不错的选择,因为 Promise 是围绕“thenables”构建的。
2
参考文献
其他可能令人困惑的事情
Promises/A 和 Promises/A+ 之间的区别
(TL;DR,Promises/A+ 主要解决 Promises/A 中的歧义)
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
are important differences).
Since it is still an evolving spec, the answer currently comes from attempting to survey both references (like wikipedia) and implementations (like jQuery):
Deferred: Never described in popular references,
1
2
3
4
but commonly used by implementations as the arbiter of promise resolution (implementing
resolve
andreject
).5
6
7
Sometimes deferreds are also promises (implementing
then
),5
6
other 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
then
functionaccepting another target function and returning a new promise.
2
Example from CommonJS:
Always described in popular references, although never specified as to
whose responsibility resolution falls to.
1
2
3
4
Always present in popular implementations, and never given
resolution abilites.
5
6
7
Future: a seemingly deprecated term found in some popular references
1
and at least one popular implementation,
8
but seemingly being phased out of discussion in preference for the term
'promise'
3
and 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
then
functionality.10
It's unclear if avoiding the term 'promise' was intentional, but probably a
good choice since promises are built around 'thenables.'
2
References
Misc potentially confusing things
Difference between Promises/A and Promises/A+
(TL;DR, Promises/A+ mostly resolves ambiguities in Promises/A)
鉴于人们明显不喜欢我试图回答OP问题的方式。字面上的答案是,promise 是与其他对象共享的东西,而 deferred 应该保持私有。首先,延迟(通常扩展 Promise)可以自行解决,而 Promise 可能无法这样做。
如果您对细节感兴趣,请查看 Promises/A+。
据我所知,首要目的是通过标准化接口提高清晰度并放松耦合。请参阅@jfriend00 的建议阅读内容:
就我个人而言,我发现 deferred 在处理例如由异步请求填充的模板、加载具有依赖网络的脚本以及以非阻塞方式提供用户反馈以形成数据时特别有用。
事实上,比较在 JS 模式下异步加载 CodeMirror 后执行某些操作的纯回调形式(抱歉,我有一段时间没有使用 jQuery):
到承诺制定的版本(再次抱歉,我'我不是最新的 jQuery):
对半伪代码表示歉意,但我希望它使核心思想更加清晰。基本上,通过返回标准化的 Promise,您可以传递 Promise,从而实现更清晰的分组。
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.
If you're interested in the minutiae, then examine Promises/A+.
So far as I'm aware, the overarching purpose is to improve clarity and loosen coupling through a standardized interface. See suggested reading from @jfriend00:
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.
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):
To the promises formulated version (again, apologies, I'm not up to date on jQuery):
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.
真正让我感兴趣的是 多梅尼克·德尼科拉 (Domenic Denicola) 的演示文稿。
在github gist中,他给出了我最喜欢的描述,非常简洁:
换句话说,promise 是一种让我们编写几乎可以编写异步代码的方式。就像同步一样容易编写。
考虑这个带有承诺的示例:
它的工作方式就像您正在编写此同步代码一样:(
如果这听起来仍然很复杂,请观看演示文稿!)
关于 Deferred,它是
.resolve()
或 < code>.reject() 承诺。在 Promises/B 规范中,它被称为.defer().在 jQuery 中,它是
$.Deferred()
。请注意,据我所知,jQuery 中的 Promise 实现已被破坏(请参阅要点),至少从 jQuery 1.8.2 开始是如此。
它应该实现 Promises/A thenables,但你没有得到正确的错误处理应该,从某种意义上说,整个“异步尝试/捕获”功能将不起作用。
遗憾的是,因为使用异步代码进行“try/catch”是非常酷的。
如果您打算使用 Promise(您应该用自己的代码尝试一下!),请使用 Kris Kowal 的 Q。 jQuery 版本只是一些回调聚合器,用于编写更干净的 jQuery 代码,但没有抓住要点。
关于Future,我不知道,我没有在任何API中看到过。
编辑: 多梅尼克·德尼科拉 (Domenic Denicola) 在 YouTube 上的关于 Promises 的演讲,来自 @Farm 下面的评论。
视频中引用迈克尔·杰克逊(是的,迈克尔·杰克逊)的话:
这是一个很好的描述:承诺就像来自未来的变量——对在某个时刻将存在(或发生)的事物的一流引用。
What really made it all click for me was this presentation by Domenic Denicola.
In a github gist, he gave the description I like most, it's very concise:
In other word, promises are a way that lets us write asynchronous code that is almost as easy to write as if it was synchronous.
Consider this example, with promises:
It works as if you were writing this synchronous code:
(If this still sounds complicated, watch that presentation!)
Regarding Deferred, it's a way to
.resolve()
or.reject()
promises. In the Promises/B spec, it is called.defer()
. In jQuery, it's$.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.
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.
Regarding Future, I have no idea, I haven't seen that in any API.
Edit: Domenic Denicola's youtube talk on Promises from @Farm's comment below.
A quote from Michael Jackson (yes, Michael Jackson) from the video:
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 代表创建 Promise 时不一定知道的值的代理。它允许您将处理程序与异步操作的最终成功值或失败原因相关联。这使得异步方法可以像同步方法一样返回值:异步方法返回在未来某个时刻具有值的承诺,而不是最终值。
https://developer.mozilla.org/en-US /docs/Web/JavaScript/Reference/Global_Objects/Promise
deferred.promise()
方法允许异步函数防止其他代码干扰进度或状态其内部要求。 Promise 仅公开附加附加处理程序或确定状态(then、done、fail、always、pipe、progress、state 和 Promise)所需的 Deferred 方法,但不公开更改状态的方法(<强>解决、拒绝、通知、resolveWith、rejectWith 和 notificationWith)。如果提供了 target,deferred.promise() 会将方法附加到其上,然后返回该对象,而不是创建一个新对象。这对于将 Promise 行为附加到已存在的对象非常有用。
如果您要创建延迟对象,请保留对延迟对象的引用,以便可以在某个时候解决或拒绝它。通过 deferred.promise() 仅返回 Promise 对象,以便其他代码可以注册回调或检查当前状态。
A Promise represents 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
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).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.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.
Promise 是最初未知的结果的占位符,而 deferred 表示结果产生值的计算。
参考
promise
represents a value that is not yet knowndeferred
represents work that is not yet finishedA promise is a placeholder for a result which is initially unknown while a deferred represents the computation that results in the value.
Reference