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

时间:2011-07-23 15:10:51

标签: javascript promise future deferred

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

5 个答案:

答案 0 :(得分:142)

这些答案,包括选定的答案,都有助于引入承诺 从概念上讲,但缺乏具体差异的具体细节 使用库实现它们时出现的术语(以及那里 重要的差异。)

由于它仍为an evolving spec,目前的答案来自于尝试调查两个引用(如wikipedia)和实现(如jQuery):

  • 延期:从未在热门推荐中描述, 1 2 3 4 但实现常用作承诺解决的仲裁者(实现resolvereject)。 5 6 7 功能

    有时延期也是承诺(实施then), 5 6 其他时候,只有Deferred才被视为更纯粹 能够解决,并迫使用户访问承诺 使用then 7 功能

  • 承诺:所讨论策略中最全面的词语。

    存储目标函数结果的代理对象 同步性我们想抽象,加上暴露then函数 接受另一个目标函数并返回一个新的承诺。 2 功能

    来自CommonJS的示例:

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

    总是在流行的参考文献中描述,尽管从未指定过 其责任解决方案属于。 1 2 3 4 功能

    始终出现在流行的实施中,从未给出过 决议能力。 5 6 7 功能

  • 未来:在一些受欢迎的参考文献中发现的一个看似弃用的术语 1 至少有一个流行的实现, 8 但似乎正在逐步退出讨论而优先于该术语 '诺言' 3 并不总是在流行的主题介绍中提到。 9 功能

    但是,至少有一个库通常使用该术语进行抽象 同步性和错误处理,同时不提供then功能。 10 目前还不清楚是否有意避免使用“承诺”一词,但可能是一个 这是一个很好的选择,因为承诺是建立在“可能的”之上的。 2 功能

参考

  1. Wikipedia on Promises & Futures
  2. Promises/A+ spec
  3. DOM Standard on Promises
  4. DOM Standard Promises Spec WIP
  5. DOJO Toolkit Deferreds
  6. jQuery Deferreds
  7. Q
  8. FutureJS
  9. Functional Javascript section on Promises
  10. Futures in AngularJS Integration Testing
  11. 其他可能令人困惑的事情

答案 1 :(得分:94)

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

如果您对细节感兴趣,请检查Promises/A+


据我所知,最重要的目的是通过标准化界面提高清晰度并放松耦合。请参阅@ jfriend00的suggested reading

  

而不是直接将回调传递给函数,而不是   可以导致紧密耦合的接口,使用promises允许一个   对同步或异步代码的单独关注。

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

实际上,比较在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.");
   });
});

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

答案 2 :(得分:72)

真正让我点击的是Domenic Denicola的this presentation

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

  

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

换句话说,promises是一种让我们编写异步代码的方法,这些代码几乎和同步一样容易编写。

考虑这个例子,使用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);
        }
    );

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

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实现已经破坏(参见gist),至少从jQuery 1.8.2开始。
它应该实现Promises/A thenables,但是你没有得到正确的错误处理,因为整个“异步尝试/捕获”功能都不起作用。 遗憾的是,因为使用异步代码进行“try / catch”非常酷。

如果您打算使用Promises(您应该使用自己的代码进行尝试!),请使用Kris Kowal's Q。 jQuery版本只是一些用于编写更清晰的jQuery代码的回调聚合器,但是忽略了这一点。

关于未来,我不知道,我在任何API中都没有看到它。

修改: Domenic Denicola's youtube talk on Promises来自@Farm的评论。

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

  

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

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

答案 3 :(得分:29)

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

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

deferred.promise()方法允许异步函数阻止其他代码干扰其内部请求的进度或状态。 Promise仅公开附加其他处理程序或确定状态所需的Deferred方法( then,done,fail,always,pipe,progress,state和promise ),但不会公开更改状态的方法(< strong> resolve,reject,notify,resolveWith,rejectWith和notifyWith )。

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

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

  

我们可以说承诺代表一个尚未知道的值,其中延迟表示尚未完成的工作。

  

enter image description here

答案 4 :(得分:21)

  • promise表示尚未知晓的值
  • deferred表示尚未完成的作业

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

参考