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的仲裁者(实现resolvereject )被实现。 5 6 7

    有时候,延期也是承诺(实现的then ),其他时候认为延期只能解决,并强迫用户访问使用的承诺。 7

  • 诺言 :正在讨论的战略中最全面的词汇。

    一个代理对象存储一个目标函数的结果,这个目标函数的同步性我们想抽象,再加上一个接受另一个目标函数的then函数并返回一个新的promise。 2

    CommonJS的例子:

     > 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,而不提供thenfunction。 10目前尚不清楚“承诺”是否是故意的,但可能是一个很好的select,因为许诺是build立在“可敬的”的基础上的。 2

参考

  1. 维基百科关于承诺和期货
  2. 承诺/ A +规格
  3. 关于承诺的DOM标准
  4. DOM标准承诺规范WIP
  5. DOJO工具包延期
  6. jQuery的延期
  7. Q
  8. FutureJS
  9. Promises的functionJavascript部分
  10. 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或检查当前状态。

简单地说,一个承诺代表一个尚未知道的价值,因为延期代表尚未完成的工作。 在这里输入图像描述