首页 文章

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

提问于
浏览
283

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

5 回答

  • 70

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

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


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

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

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

    实际上,比较在JS模式下异步加载CodeMirror后做的事情的纯回调形式(道歉,我没有在 while 中使用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.");
       });
    });
    

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

  • 93

    这些答案,包括选定的答案,都有助于在概念上引入承诺,但缺乏具体说明在使用实现它们的库时出现的术语中的差异究竟是什么(并且存在重要的差异) .

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

    • Deferred :从未在流行的参考文献中描述,但通常被实现用作承诺解决的仲裁者(实现 resolvereject ) . 5 6 7

    有时延迟也是承诺(实现 then ),其他时候看起来更纯粹的是让Deferred只能解析,并强制用户访问使用 then 的承诺 . 7

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

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

    CommonJS中的示例:

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

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

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

    • Future :在一些受欢迎的参考文献1和至少一个流行的实现中发现了一个看似被弃用的术语,8但似乎逐渐退出讨论而优先于术语'promise' 3并且在该主题的流行介绍中并不总是提及 . 9

    但是,至少有一个库通常使用该术语来抽象同步性和错误处理,同时不提供 then 功能 . 10它's unclear if avoiding the term '承诺' was intentional, but probably a good choice since promises are built around ' thenables . ' 2

    参考文献

    其他可能令人困惑的东西

    (TL; DR,Promises / A主要解决Promises / A中的歧义)

  • 20

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

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

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

    换句话说,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代码的聚合器,但是忽略了这一点 .

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

    Edit: Domenic Denicola's youtube talk on Promises来自@Farm的评论如下 .

    迈克尔 Jackson (是的,迈克尔 Jackson )从视频中引用:

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

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

  • 25
    • promise 表示尚不知道的值

    • deferred 代表尚未完成的工作

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

    参考

  • 137

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

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

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

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

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

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


相关问题