延期、承诺和期货有什么区别? 这三者背后是否有一个普遍认可的理论?
当前回答
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方法,而不公开更改状态(resolve、reject、notify、resolveWith、rejectWith和notifyWith)的Deferred方法。
如果提供了target, deferred.promise()将把方法附加到它上面,然后返回这个对象,而不是创建一个新的对象。这对于将Promise行为附加到已经存在的对象非常有用。
如果您正在创建一个Deferred对象,请保留对该Deferred对象的引用,以便在某个时候可以解析或拒绝它。仅通过deferred.promise()返回Promise对象,以便其他代码可以注册回调或检查当前状态。
我们可以简单地说,Promise代表一个还不知道的值,而Deferred代表尚未完成的工作。
其他回答
承诺表示一个还不知道的值 deferred表示尚未完成的工作
promise是最初未知结果的占位符,而deferred则表示产生该值的计算。
参考
http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics
这些答案,包括所选的答案,都有助于介绍承诺 概念上,但缺乏具体的差异到底在哪里 使用库实现它们时出现的术语 是重要的区别)。
由于它仍然是一个不断发展的规范,目前的答案来自于试图调查引用(如维基百科)和实现(如jQuery):
Deferred: Never described in popular references, 1 2 3 4 but commonly used by implementations as the arbiter of promise resolution (implementing resolve and reject). 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 function 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. 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
参考文献
关于承诺和未来的维基百科 承诺/ +规范 DOM承诺标准 DOM标准承诺规范在制品 DOJO Toolkit延迟 jQuery递延 问 FutureJS 函数式Javascript的承诺部分 AngularJS集成测试中的期货
杂项可能会混淆事情
Promises/A和Promises/A+的区别 (TL;DR, Promises/A+主要解决Promises/A中的歧义)
真正让我心动的是Domenic Denicola的演讲。
在github的一个要点中,他给出了我最喜欢的描述,非常简洁:
承诺的意义在于让我们回到异步世界中的函数组合和错误冒泡。
换句话说,承诺是一种让我们编写异步代码的方式,它几乎像编写同步代码一样容易。
看看下面这个例子:
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);
}
(如果这听起来还是很复杂,那就去看看那个演示吧!)
对于Deferred,它是.resolve()或.reject()承诺的一种方式。在Promises/B规范中,它被称为.defer()。在jQuery中,它是$. deferred()。
请注意,据我所知,jQuery中的Promise实现被打破了(见要点),至少在jQuery 1.8.2中是这样。 它应该实现Promises/A thenabled,但你没有得到正确的错误处理,在某种意义上,整个“async try/catch”功能将不起作用。 这很遗憾,因为在异步代码中使用“try/catch”非常酷。
如果你打算使用Promises(你应该在你自己的代码中尝试一下!),使用Kris Kowal的Q. jQuery版本只是一些回调聚合器,用于编写更简洁的jQuery代码,但没有抓住重点。
至于Future,我不知道,我在任何API中都没有看到过。
编辑:Domenic Denicola在youtube上关于承诺的演讲来自@Farm下面的评论。
视频中迈克尔·杰克逊(没错,迈克尔·杰克逊)的一句话:
我想让你记住这句话: promise是一个异步值。
这是一个很好的描述:一个承诺就像一个来自未来的变量——一个在某一时刻将存在(或发生)的事物的一级参考。
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方法,而不公开更改状态(resolve、reject、notify、resolveWith、rejectWith和notifyWith)的Deferred方法。
如果提供了target, deferred.promise()将把方法附加到它上面,然后返回这个对象,而不是创建一个新的对象。这对于将Promise行为附加到已经存在的对象非常有用。
如果您正在创建一个Deferred对象,请保留对该Deferred对象的引用,以便在某个时候可以解析或拒绝它。仅通过deferred.promise()返回Promise对象,以便其他代码可以注册回调或检查当前状态。
我们可以简单地说,Promise代表一个还不知道的值,而Deferred代表尚未完成的工作。
鉴于我显然不喜欢我试图回答OP问题的方式。字面上的答案是,承诺是与其他对象共享的东西,而deferred应该保持私有。基本上,deferred(通常扩展了Promise)可以自行解决问题,而Promise则不能。
如果你对细节感兴趣,可以看看Promises/A+。
据我所知,其主要目的是通过标准化接口提高清晰度和放松耦合。参见@jfriend00的建议阅读:
而不是直接将回调函数传递给函数 可以导致紧密耦合的接口,使用承诺允许一个 对于同步或异步的代码,需要单独考虑。
就我个人而言,我发现在处理由异步请求填充的模板时,延迟特别有用,加载有依赖网络的脚本,并以非阻塞的方式提供用户反馈以形成数据。
实际上,比较在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.");
};
});
对于承诺的表述版本(再次道歉,我不是最新的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.");
});
});
很抱歉使用了半伪代码,但我希望它能使核心思想更清楚。基本上,通过返回标准化的承诺,您可以传递承诺,从而实现更清晰的分组。
推荐文章
- 如何使用Jest测试对象键和值是否相等?
- 将长模板文字行换行为多行,而无需在字符串中创建新行
- 如何在JavaScript中映射/减少/过滤一个集?
- Bower: ENOGIT Git未安装或不在PATH中
- 添加javascript选项选择
- 在Node.js中克隆对象
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 使用JavaScript更改URL参数并指定默认值
- 在window.setTimeout()发生之前取消/终止
- 如何删除未定义和空值从一个对象使用lodash?
- 检测当用户滚动到底部的div与jQuery
- 在JavaScript中检查字符串包含另一个子字符串的最快方法?
- 检测视口方向,如果方向是纵向显示警告消息通知用户的指示
- ASP。NET MVC 3 Razor:在head标签中包含JavaScript文件
- 禁用从HTML页面中拖动图像