defer().promise 和 Promise 的区别

IT技术 javascript promise
2021-02-02 02:32:16

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

提前致谢

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

1个回答

嗯,这就是关于promise解析源。Q 和一堆其他库提供了两个 API:

  • 遗留deferAPI - 您可以在其中创建一个延迟,.resolve(value) 并且它有一个可以返回的Promise。
  • 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?

好吧,延迟 API 是第一位的。这是其他一些语言如何处理它,这是论文如何处理它以及人们首先如何使用它 - 但是 - 这两种 API 之间存在重要区别。Promise构造函数是安全的。

投掷安全

Promise 抽象异常处理并且是安全抛出的。如果您在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);
});

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

@klamtlne 是的。这就是我所说的 :) 你可以在这里阅读更多关于基本原理的信息:github.com/promises-aplus/constructor-spec/issues
2021-03-18 02:32:16
在最后一个片段中,您似乎正在处理 .success 回调中的异常then()我确定我不理解某些东西,但不应该是这样的:return get().then(function(s) { /* success */ }, function(e){ return handleException(e); });
2021-03-20 02:32:16
另外,我发现很难理解为什么 Q.promise 不公开诸如then. 如果它针对过程控制,则不应公开resolvereject
2021-03-26 02:32:16
这意味着,如果我们使用 defer().promise,我们必须手动处理错误,否则它会弹出窗口。在 Promise 构造函数中,您不必担心,这就是throw 安全性的区别
2021-03-27 02:32:16
@klamtlnenew Q.Promise(...)从创建源构造一个新的 promise。创建的对象是一个确实有then方法的Promise另见:blog.domenic.me/the-revealing-constructor-pattern
2021-04-02 02:32:16