JavaScript中Deferred、Promise和Future的区别是什么?

延期、承诺和期货之间有什么区别?< br > 这三者背后是否有一个普遍认可的理论?< / p >
110850 次浏览

鉴于我显然不喜欢我试图回答OP问题的方式。字面上的答案是,承诺是与其他对象共享的东西,而deferred应该保持私有。基本上,deferred(通常扩展了Promise)可以自行解决问题,而Promise则不能。

如果你对细节感兴趣,那么检查承诺/ +


据我所知,其主要目的是通过标准化接口提高清晰度和放松耦合。参见@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.");
});
});

很抱歉使用了半伪代码,但我希望它能使核心思想更清楚。基本上,通过返回标准化的承诺,您可以传递承诺,从而实现更清晰的分组。

真正让我感兴趣的是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()承诺的一种方式。在承诺/ B规范中,它被称为.defer()。在jQuery中,它是$.Deferred()

请注意,据我所知,承诺实现在jQuery是坏的(见主旨),至少在jQuery 1.8.2 它应该实现承诺/ thenables,但你没有得到你应该得到的正确错误处理,在某种意义上,整个“async try/catch”功能将不起作用。 这是一个遗憾,因为在异步代码中使用“try/catch”非常酷

如果你打算使用promise(你应该在自己的代码中尝试它们!),使用克里斯·科瓦尔的Q。jQuery版本只是一些回调聚合器,用于编写更清晰的jQuery代码,但忽略了这一点。

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

下面@Farm的注释中的编辑: Domenic Denicola关于承诺的youtube演讲

视频中迈克尔·杰克逊的一句话(是的,迈克尔•杰克逊):

我想让你记住这句话: promise是异步价值< / em >

这是一个很好的描述:一个承诺就像一个来自未来的变量——一个在某一时刻将存在(或发生)的事物的一级参考。

这些答案,包括所选的答案,都是用来介绍承诺的 概念上,但缺乏具体的差异到底在哪里 使用库实现它们时出现的术语 重要差异)。

由于它仍然是不断发展的规范,目前的答案来自于试图调查引用(如维基百科)和实现(如jQuery):

  • 递延:从未在流行的参考文献中描述, 1 2 3 4 但通常被实现用作承诺解析的仲裁者(实现resolvereject)。 5 6 7 < /一口> < / p > 有时候延迟也是承诺(实现then), 5 6 其他时候,它被认为是更纯粹的只有延期 能够解决,并强制用户访问的承诺 使用then 7 < /一口> < / p > < /李>

  • 承诺:正在讨论的策略的最全面的词。

    一个代理对象,存储目标函数的结果 我们想要抽象的同步性,再加上公开then函数 接受另一个目标函数并返回一个新的承诺。 2 < /一口> < / p >

    来自CommonJS的例子:

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

    ,

    经常在流行的参考文献中描述,尽管从未指定为 决议由谁负责。 1 2 3 4 < /一口> < / p >

    总是出现在流行的实现中,从未给出 决议的能力。 5 6 7 < /一口> < / p > < /李>

  • 未来:在一些流行的参考文献中发现的一个看似被弃用的术语 1 至少有一种流行的实现, 8 但似乎正在逐步退出讨论,取而代之的是这个术语 “承诺” 3 在这个话题的流行介绍中并不总是被提及。 9 < /一口> < / p > 然而,至少有一个库将这个术语用于抽象 同步和错误处理,而不提供then功能。 10 目前尚不清楚避免使用“承诺”一词是否有意为之,但可能是出于某种原因 这是个不错的选择,因为承诺是围绕着“thenabling”建立的。 2 < /一口> < / p > < /李>

参考文献

  1. 维基百科的承诺&期货< / >
  2. 承诺/a + spec .
  3. DOM承诺标准
  4. DOM标准承诺Spec WIP
  5. DOJO Toolkit Deferreds
  6. jQuery Deferreds
  7. Q
  8. FutureJS
  9. 承诺的功能Javascript部分
  10. AngularJS集成测试中的期货

杂项可能会混淆事情

  • promise表示一个未知的值
  • deferred表示尚未完成的工作

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

参考

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

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

deferred.promise()方法允许异步函数防止其他代码干扰其内部请求的进度或状态。Promise只公开附加附加处理程序或确定状态(然后,完成,失败,总是,管道,进步,声明和承诺)所需的Deferred方法,而不公开改变状态(resolve, reject, notify, resolveWith, rejectWith, notifyWith)的Deferred方法。

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

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

我们可以简单地说,承诺表示一个还不知道的值,而递延表示尚未完成的工作。


enter image description here