314

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

4

5 回答 5

147

这些答案,包括选定的答案,对于在概念上介绍 Promise 很有用,但缺乏具体说明在使用实现它们的库时出现的术语中的确切差异(并且存在 重要差异)。

由于它仍然是一个不断发展的规范,因此目前的答案来自尝试调查参考资料(如wikipedia)和实现(如jQuery):

  • Deferred:从未在流行的参考文献中描述过, 1 2 3 4 但通常被实现用作 promise 解决方案的仲裁者(实现and )。 5 6 7 resolvereject

    有时 deferred 也是 promise(实现then), 5 6 其他时候,让 Deferred 仅能够解析并强制用户访问 promise 以使用. 7 then

  • 承诺:对正在讨论的战略最包罗万象的词。

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

    来自CommonJS的示例:

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

     

    总是在流行的参考资料中有所描述,尽管从未指定谁的责任解决方案。 1 2 3 4

    始终存在于流行的实现中,并且从未赋予解析能力。 5 6 7

  • Future:在一些流行的参考文献 1 和至少一个流行的实现中发现的一个看似已弃用的术语, 8 但似乎正在逐步退出讨论,优先考虑术语“promise” 3 并且在该主题的流行介绍中并不总是提到。 9

    但是,至少有一个库通常使用该术语来抽象同步性和错误处理,但不提供then功能。 10 目前尚不清楚是否有意避免使用“承诺”一词,但这可能是一个不错的选择,因为承诺是围绕“thenables”构建的。 2

参考

  1. 关于承诺和未来的维基百科
  2. 承诺/A+ 规范
  3. Promise 上的 DOM 标准
  4. DOM 标准承诺规范 WIP
  5. DOJO 工具包延期
  6. jQuery 延迟
  7. 未来JS
  8. 关于 Promises 的函数式 Javascript 部分
  9. AngularJS 集成测试的未来

其他可能令人困惑的事情

于 2013-09-17T19:13:52.850 回答
100

鉴于我明显不喜欢我试图回答 OP 的问题。字面上的答案是,promise 是与其他对象共享的东西,而 deferred 应该保持私有。首先,deferred(通常扩展 Promise)可以自行解决,而 Promise 可能无法这样做。

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


据我所知,首要目的是通过标准化接口提高清晰度并放松耦合。请参阅@jfriend00 的建议阅读

与其直接将回调传递给函数(这会导致接口紧密耦合),不如使用 Promise 允许人们分离对同步或异步代码的关注点。

就个人而言,我发现 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.");
   };
});

对于 promises 制定的版本(再次道歉,我不是最新的 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.");
   });
});

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

于 2011-07-26T03:13:20.540 回答
73

Domenic Denicola 的这次演讲真正让我觉得这一切都对我来说很有吸引力。

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

Promise 的目的是让我们在异步世界中恢复功能组合和错误冒泡。

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

考虑这个带有承诺的例子:

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 1.8.2 中,jQuery 中的 Promise 实现已损坏(请参阅该要点)。
它应该实现Promises/A thenables,但是你没有得到你应该得到的正确错误处理,因为整个“异步尝试/捕获”功能将不起作用。很遗憾,因为使用异步代码进行“try/catch”是非常酷的。

如果你打算使用 Promises(你应该用你自己的代码尝试一下!),使用Kris Kowal 的 Q。jQuery 版本只是一些用于编写更简洁的 jQuery 代码的回调聚合器,但没有抓住重点。

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

编辑: Domenic Denicola 的 youtube 上关于 Promises 的演讲来自@Farm下面的评论。

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

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

这是一个很好的描述:promise 就像来自未来的变量 - 对在某些时候将存在(或发生)的事物的一流引用。

于 2012-11-23T06:48:28.703 回答
33

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),但不公开改变状态的方法(resolve、reject、notify、resolveWith、 rejectWith 和 notifyWith)。

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

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

简单地说,Promise代表一个未知的值,而Deferred代表尚未完成的工作。


在此处输入图像描述

于 2016-02-03T06:42:53.147 回答
24
  • Apromise代表一个未知的值
  • Adeferred代表尚未完成的工作

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

参考

于 2014-09-24T14:28:33.807 回答