JavaScript中的Deferred,Promise和Future有什么区别?
递延,承诺和期货有什么区别?
这三者背后有一个普遍认可的理论吗?
鉴于我显然不喜欢我试图回答OP的问题。 字面上的答案是,承诺是与其他对象共享的东西,而延迟应该保持私有。 首先,延期(通常延伸诺言)可以自行解决,而承诺可能无法做到。
如果你对细节感兴趣的话,可以查看Promises / A + 。
就我所知,总体目标是通过标准化的界面来提高清晰度和放松耦合。 请参阅@ jfriend00的build议阅读 :
不是直接将callback函数传递给函数,而是通过使用promise来导致紧密耦合的接口,从而可以分别关注同步或asynchronous的代码。
就我个人而言,在处理由asynchronous请求填充的模板,加载具有依赖性networking的脚本以及提供用户反馈以非阻塞方式形成数据时,我发现延迟特别有用。
事实上,比较在JS模式下asynchronous加载CodeMirror之后做一些事情的纯callbackforms(道歉,我没有在一段时间使用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."); }; });
对诺言制定的版本(再次,道歉,我不是最新的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."); }); });
道歉的半伪代码,但我希望它使核心思想有点清楚。 基本上,通过返回一个标准化的承诺,你可以传递承诺,从而允许更清晰的分组。
这些答案,包括选定的答案,对于从概念上引入承诺是有好处的,但缺乏使用实现它们的库时产生的术语( 具有重要差异)的具体细节。
由于它仍然是一个不断发展的规范 ,现在的答案来自于试图调查两个引用(如维基百科 )和实现(如jQuery ):
-
延迟 :从未在stream行的参考文献中描述过,但通常作为承诺parsing的仲裁者(实现
resolve
和reject
)被实现。 5 6 7有时候,延期也是承诺(实现的
then
),其他时候认为延期只能解决,并强迫用户访问使用的承诺。 7 -
诺言 :正在讨论的战略中最全面的词汇。
一个代理对象存储一个目标函数的结果,这个目标函数的同步性我们想抽象,再加上一个接受另一个目标函数的
then
函数并返回一个新的promise。 2CommonJS的例子:
> asyncComputeTheAnswerToEverything() .then(addTwo) .then(printResult); 44
总是在stream行的参考文献中描述,尽pipe从来没有具体说明解决谁的责任。 1 2 3 4
总是出现在stream行的实现,并没有给解决abilites。 5 6 7
-
未来 :在一些stream行的参考资料1和至less一个受欢迎的实施scheme中发现了一个看似不赞成的术语1 ,但似乎正在逐渐退出讨论阶段,偏向于“承诺” 3这个术语,在这个主题的热门介绍中并不总是提到。 9
但是,至less有一个库通常使用该术语来抽象同步性和error handling,而不提供
then
function。 10目前尚不清楚“承诺”是否是故意的,但可能是一个很好的select,因为许诺是build立在“可敬的”的基础上的。 2
参考
- 维基百科关于承诺和期货
- 承诺/ A +规格
- 关于承诺的DOM标准
- DOM标准承诺规范WIP
- DOJO工具包延期
- jQuery的延期
- Q
- FutureJS
- Promises的functionJavascript部分
- AngularJS集成testing中的期货
其他可能令人困惑的事情
-
承诺/ A和承诺/ A +之间的区别
(TL; DR,Promises / A +主要解决Promises / A中的含糊不清)
Domenic Denicola 介绍了这个演示 。
在Github的主旨中 ,他给出了我最喜欢的描述,非常简洁:
承诺的重点是让我们回到asynchronous世界的function组成和错误冒泡。
换句话说,承诺是一种让我们编写asynchronous代码的方式,就像写同步一样简单。
考虑这个例子,承诺:
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); } );
它的工作原理就好像你在编写这个同步代码一样:
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); }
(如果这听起来还是很复杂的话,那么请看这个演示!
关于延迟,这是一个方法.resolve()
或.reject()
承诺。 在Promises / B规范中,它被称为.defer()
。 在jQuery中,它是$.Deferred()
。
请注意,就我所知,jQuery中的Promise实现已经被破坏(请参阅这个要点),至less从jQuery 1.8.2开始。
它应该实现了Promises / A可执行文件 ,但是你不应该得到正确的error handling,因为整个“async try / catch”function不起作用。 这是一个遗憾,因为使用asynchronous代码“try / catch”是非常酷的。
如果你打算使用Promises(你应该用你自己的代码来试用它们),请使用Kris Kowal的Q. jQuery版本只是一些callback聚合器,用于编写更干净的jQuery代码,但是忽略了一点。
关于未来,我不知道,我没有看到在任何API。
编辑: Domenic Denicola的youtube从下面的@Farm的评论谈论诺言 。
迈克尔·jackson(是的, 迈克尔·jackson )从录像引用:
我希望你在脑海中刻录这句话: 一个承诺是一个asynchronous的价值 。
这是一个很好的描述:一个承诺就像是一个未来的variables – 一个对某些事物的一stream参考,在某些时候,将会存在(或发生)。
- 一个
promise
代表一个尚不知道的价值 -
deferred
代表尚未完成的工作
承诺是一个结果的占位符,最初是未知的,而延迟表示计算结果的值。
参考
一个承诺代表一个价值的代理人,当承诺被创造时不一定知道。 它允许您将处理程序与asynchronous操作的最终成功值或失败原因相关联。 这使得asynchronous方法可以像同步方法那样返回值:asynchronous方法将返回一个在未来某个时间点具有值的承诺,而不是最终值。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
deferred.promise()方法允许asynchronous函数防止其他代码干扰其内部请求的进度或状态。 Promise公开了只附加附加处理程序或者确定状态(然后,完成,失败,总是,pipe道,进度,状态和承诺)所需的Deferred方法,但是没有改变状态(resolve,reject,notify,resolveWith, rejectWith和notifyWith)。
如果提供了target,deferred.promise()会将方法附加到它上面,然后返回这个对象而不是创build一个新的对象。 将Promise行为附加到已存在的对象可能会很有用。
如果您正在创build延期,请保留对延期的引用,以便在某个时刻可以解决或拒绝。 其他代码可以通过deferred.promise()方法返回Promise对象,以便注册callback或检查当前状态。
简单地说,一个承诺代表一个尚未知道的价值,因为延期代表尚未完成的工作。