JavaScript中Deferred,Promise和Future之间有什么区别?

Tow*_*wer 297 javascript future promise deferred

延期,承诺和期货有什么区别?
这三者背后是否有普遍认可的理论?

Woa*_*dae 144

这些答案,包括所选择的答案,是良好的概念引入的承诺,但在细节缺乏究竟差别在使用图书馆实现它们(还有时出现的术语 重要的区别).

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

  • 推迟:从不在流行参考文献中所述, 1 2 3 4 作为承诺分辨率(实施仲裁器,但常用的实现方式和). 5 6 7 resolvereject

    有时deferreds也承诺(实现then), 5个6 其他时候它看作是更纯粹的有递延只能分辨率,并迫使用户访问的承诺使用. 7 then

  • 承诺:正在讨论的战略中最全面的词.

    一个代理对象,存储我们想要抽象的同步性的目标函数的结果,以及then接受另一个目标函数并返回一个新的promise的函数. 2

    CommonJS的示例:

    > asyncComputeTheAnswerToEverything()
        .then(addTwo)
        .then(printResult);
    44
    
    Run Code Online (Sandbox Code Playgroud)

     

    总是在流行的参考文献中描述,尽管从未指明谁的责任解决方案. 1 2 3 4

    始终存在于流行的实现中,并且永远不会给出解决方案. 5 6 7

  • 未来:在一些热门的参考文献中一个看似过时期限 1 和至少一个流行的实现, 8 但看似偏爱"承诺"一词被淘汰的讨论 3 ,不要总是在介绍流行的话题提及. 9

    但是,至少有一个库通常使用该术语来抽象同步性和错误处理,而不提供then功能. 10 目前还不清楚是否有意避免使用"承诺"一词,但可能是一个很好的选择,因为承诺是围绕'可能的'建立的. 2

参考

  1. 承诺与期货维基百科
  2. 承诺/ A +规格
  3. 承诺的DOM标准
  4. DOM标准承诺规范WIP
  5. DOJO工具包延期
  6. jQuery Deferreds
  7. Q
  8. FutureJS
  9. 关于Promises的功能性Javascript部分
  10. AngularJS集成测试中的未来

杂项可能让人感到困惑

  • 为了对"未来"一词进行更多澄清 - 期货在许多编程语言中有着悠久的历史,可以追溯到80年代中期.这个术语今天仍然广泛使用,特别是在JVM上.JavaScript似乎选择使用术语"Promise"来表示类似于Java所指的"Future".Scala将相同的概念分为"Future"和"Promise",以引用"read"句柄和JavaScript程序员称之为Promise的"write"句柄. (4认同)

fnc*_*omp 97

显然不喜欢我试图回答OP的问题.字面上的答案是,承诺是与其他对象共享的东西,而延迟应该保密.主要是,延迟(通常扩展为Promise)可以自行解决,而承诺可能无法解决.

如果你对细节感兴趣,那么检查Promises/A +.


据我所知,最重要的目的是通过标准化界面提高清晰度并放松耦合.查看来自@ jfriend00的建议阅读:

不是直接将回调传递给函数,而是使用promises可以导致紧密耦合的接口,而是可以分离对同步或异步代码的关注.

就个人而言,我发现deferred在处理例如由异步请求填充的模板,加载具有依赖关系网络的脚本以及提供用户反馈以非阻塞方式形成数据时特别有用.

事实上,比较做一些纯回调形式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.");
   };
});
Run Code Online (Sandbox Code Playgroud)

对承诺制定的版本(再次,道歉,我不是最新的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.");
   });
});
Run Code Online (Sandbox Code Playgroud)

为半伪代码道歉,但我希望它使核心思想有些清晰.基本上,通过返回标准化的承诺,您可以传递承诺,从而允许更清晰的分组.

  • 虽然这个答案可能有用,但它并没有事实上解决这个问题:所谓的延期是期货或承诺,取决于实施. (9认同)
  • 这完全错了,您的示例与回调一样容易.Promise不是关于回调聚合和解耦,而是提供DSL来编写异步代码,如同步代码.特别是`fn(callback,errback)`与`fn()没有更紧密耦合或更少有用.然后(callback,errback)` - 但这仍然是使用promises的错误方法.我特别讨厌货物崇拜`$ .when`的例子 - 绝对没有理由你不能有一个与回调有关的`$ .when`功能. (2认同)

Cam*_*tin 72

Domenic Denicola的这次演讲让我真正点击了这一切.

github的要点中,他给出了我最喜欢的描述,它非常简洁:

承诺的重点是让我们回到异步世界中的功能组合和错误冒泡.

换句话说,promises是一种允许我们编写异步代码的方式,它几乎像同步一样容易编写.

考虑这个例子,承诺:

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);
        }
    );
Run Code Online (Sandbox Code Playgroud)

它就像你在编写这个同步代码一样:

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);
}
Run Code Online (Sandbox Code Playgroud)

(如果这仍然听起来很复杂,请观看该演示!)

关于延期,这是一种方式.resolve().reject()承诺.在Promises/B规范中,它被称为.defer().在jQuery中,它是$.Deferred().

请注意,据我所知,jQuery中的Promise实现已经破坏(参见gist),至少从jQuery 1.8.2开始.
它应该实现Promises/A thenables,但是你没有得到正确的错误处理,因为整个"异步try/catch"功能都不起作用.遗憾的是,因为拥有异步代码的"try/catch"非常酷.

如果你要使用的承诺(你应该尝试他们用自己的代码!),用克里斯科瓦尔Q值.jQuery版本只是一些用于编写更清晰的jQuery代码的回调聚合器,但是忽略了这一点.

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

编辑: Domenic Denicola对承诺YouTube的谈话@Farm下面的评论.

迈克尔·杰克逊(是的,迈克尔·杰克逊)在视频中引述:

我希望你在脑海中刻录这句话: 承诺是一种异步价值.

这是一个很好的描述:承诺就像是来自未来的变量 - 对某些东西的一流参考,在某种程度上,它将存在(或发生).

  • W3和Chrome核心团队成员对Futures(现在在DOM中实现!)的一个很好的解释可以在这里找到:http://www.xanthir.com/b4PY0 (5认同)

IRS*_*HAD 29

一个承诺代表某个值的代理创建承诺时未必知道.它允许您将处理程序与异步操作的最终成功值或失败原因相关联.这允许异步方法返回类似于同步方法的值:异步方法返回一个在将来的某个时刻具有值的承诺,而不是最终值.

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

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

如果提供了target,deferred.promise()则将方法附加到其上,然后返回此对象而不是创建新对象.这可以用于将Promise行为附加到已存在的对象.

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

简单地说,我们可以说Promise表示一个尚未知道的值,其中Deferred表示尚未完成的工作.


在此输入图像描述

  • 加 1 作为图表表示。布拉维西莫!!^_^ (2认同)

mat*_*mus 22

  • A promise表示尚未知道的值
  • A deferred表示尚未完成的工作

promise是结果的占位符,最初是未知的,而deferred表示导致值的计算.

参考