【问题标题】:Difference between defer().promise and Promisedefer().promise 和 Promise 的区别
【发布时间】:2015-04-25 14:09:54
【问题描述】:

我知道defer是把promise状态控制和进程分开的,这里以Q为例,Q.defer().promiseQ.Promise返回的promise是完全不同的,为什么要这样设计呢?以及这两个“Promise”有什么区别

提前致谢

PS:我目前正在开发 Promise 库,欢迎提出问题和 PRS:https://github.com/jiananshi/Promise-polyfill

【问题讨论】:

  • @Claies 绝对不是,如果你已经阅读了这两个问题
  • @Claies 我确实读过它,它的作用与 Defer 完全一样,不知何故,我想称它为 sugar method。让我们深入看看 Q,Q.promise 也返回方法:resolvereject github.com/kriskowal/q/blob/v1/q.js#L634-L652 但它与 ES6 Promise 略有不同,resolve 的表现很奇怪。我正在努力理解这个的设计目的
  • ״.defer" 是旧 API,"new Promise" 是新 API。新库仅支持后者。原因是构造函数版本是 throw-safe。
  • @Claies 这不是骗子……我不知道你为什么会这么认为。

标签: javascript promise


【解决方案1】:

嗯,这是关于承诺解决方案的来源。 Q 和许多其他库提供了两个 API:

  • 旧版defer API - 您可以在其中创建一个可以.resolve(value) 的延迟,并且它有一个可以返回的承诺。
  • Promise 构造函数 - 这是现代 API,您可以在其中从完成源创建 Promise。

大致做:

var d = Q.defer();
setTimeout(function(){ d.resolve(); }, 1000); 
return d.promise;

等同于:

return new Promise(function(resolve, reject){
   setTimeout(resolve, 1000);
});

所以你可能会问

为什么我们需要两个 API?

好吧,defer API 是第一位的。这是其他一些语言如何处理它,这是论文如何处理它以及人们如何首先使用它 - 然而 - 这两个 API 之间存在重要差异。 Promise 构造函数是安全的。

投掷安全

承诺抽象异常处理并且是抛出安全的。如果你抛出一个承诺链,它会将该异常转换为拒绝,引用规范:

如果 onFulfilled 或 onRejected 抛出异常 e,则 promise2 必须以 e 为理由被拒绝

假设您正在从 XHR 请求中解析 JSON:

function get(){
    var d = Q.defer();
    if(cached) { // use cached version user edited in localStorage
        d.resolve(JSON.parse(cached));
    } else { // get from server
       myCallbackApi('/foo', function(res){ d.resolve(res); });
    }
}

现在,让我们看看 Promise 构造函数的版本:

function get(){
    return new Promise(function(resolve, reject){ 
        if(cached) { // use cached version user edited in localStorage
            resolve(JSON.parse(cached));
        } else { // get from server
           myCallbackApi('/foo', resolve);
        }
    });
}

现在,假设您的服务器以某种方式向您发送了无效的 JSON(或用户将其编辑为无效状态)并且您缓存了它。

在延迟版本中 - 它同步抛出。因此,您通常必须防范它。在底层版本中它没有。顶级版本用法如下所示:

try{
  return get().catch(function(e){
     return handleException(e); // can also just pass as function
  });
} catch(e){ 
   handleException(e);
}

在底层版本中——promise 构造函数会将throws 转换为拒绝,所以这样做就足够了:

return get().then(function(e){
   return handleException(e);
});

防止发生一整类程序员错误。

【讨论】:

  • 这意味着,如果我们使用 defer().promise,我们必须手动处理错误,否则它会弹出到窗口。在 Promise 构造函数中,您不必担心,这就是 throw safety 的区别
  • @klamtlne 是的。这就是我所说的 :) 你可以在这里阅读更多关于基本原理的信息:github.com/promises-aplus/constructor-spec/issues
  • 另外,我很难理解为什么 Q.promise 不公开像 then 这样的方法。如果它针对的是过程控制,则不应暴露resolvereject
  • @klamtlne new Q.Promise(...) 从创建源构造一个新的承诺。创建的对象是一个确实有then 方法的promise。另请参阅:blog.domenic.me/the-revealing-constructor-pattern
  • 在最后的 sn-p 中,您似乎正在处理 then() 的成功回调中的异常。我确定我不理解某些东西,但不应该是这样:return get().then(function(s) { /* success */ }, function(e){ return handleException(e); });
猜你喜欢
  • 2018-03-12
  • 2017-05-23
  • 2016-12-07
  • 2019-01-20
  • 1970-01-01
  • 2017-02-06
相关资源
最近更新 更多