簡體   English   中英

Bluebird.JS承諾:新Promise(函數(解析,拒絕){})vs Promise.try(function(){})

[英]Bluebird.JS Promise: new Promise(function (resolve, reject){}) vs Promise.try(function(){})

我什么時候應該使用哪個? 以下是相同的嗎?

新的Promise()示例:

function multiRejectExample(){ 
  return new Promise(function (resolve, reject){
    if(statement){
      console.log('statement 1');
      reject(throw new Error('error'));
    }
    if(statement){
     console.log('statement 2');
     reject(throw new Error('error')); 
   }
  });
}

Promise.try()示例:

function tryExample(){
  return Promise.try(function(){
    if(statement){
      console.log('statement 1');
      throw new Error('error');
    }
    if(statement){
     console.log('statement 2');
     throw new Error('error'); 
   }
  });
}

在這種情況下,您可以主要使用(具有一個行為差異)。 第一個是標准承諾功能,可以與任何promise庫一起使用。

Promise.try()是一個由Bluebird庫專門實現的功能,並不是我所知道的任何標准流程的一部分。

使用Promise.try()的原因是,如果您有一個返回promise的函數,但生成該promise的代碼也可能導致同步異常。 由於該異常不在任何promise處理程序中,因此您可以混合使用錯誤處理。 某些代碼執行路徑可能會導致返回將要解析或拒絕的promise,而其他代碼執行路徑可能會引發異常。 要安全地編寫代碼,您必須同時響應promise並在代碼周圍放置一個try / catch塊,這些代碼變得難以處理。

Promise.try()只是一種自動捕獲任何異常並將其轉化為拒絕的方法(類似於.then()處理程序中發生的情況)。

在這兩種情況下, Promise.try()不會以這種方式使您受益,因為new Promise()回調已經捕獲異常並將它們變為拒絕,因此在那里已經為您完成了功能。 你可以在這里看到: http//jsfiddle.net/jfriend00/wLov9844/

Bluebird doc提供了這個示例,它更清楚地顯示了這個好處:

function getUserById(id) {
    return Promise.try(function() {
        if (typeof id !== "number") {
            // Courtesy of Promise.try() this exception will be turned 
            // into a returned promise that is rejected with the 
            // exception as the reason
            throw new Error("id must be a number");
        }
        return db.getUserById(id);
    });
}

getUserById().then(successFn, errFn);

在這里使用Promise.try()可以確保getUserById()始終返回一個promise,即使該方法內部的代碼同步拋出異常。 這簡化了getUserById()使用,因為您始終只需響應promise,而不必使用自己的異常處理程序。

如果沒有Promise.try() ,你可以自己編寫相同的代碼(以捕獲函數內的所有可能的同步異常):

function getUserById(id) {
    try {
        if (typeof id !== "number") {
            throw new Error("id must be a number");
        }
        return db.getUserById(id);
    } catch(e) {
        return Promise.reject(e);
    }
}

getUserById().then(successFn, errFn);

或者,您可以像這樣編碼:

function getUserById(id) {
    if (typeof id !== "number") {
        throw new Error("id must be a number");
    }
    return db.getUserById(id);
}

try {
    getUserById().then(successFn, errFn);
} catch(e) {
    errFn(e);
}

據推測,你可以看到Promise.try()在某些情況下如何簡化事情。


僅供參考,在您的第一個示例中,您使用的語法無效。 你可以這樣做:

reject(throw new Error('error')); 

我假設你的意思是這樣的:

reject(new Error('error')); 

雖然我認為這不是你所要求的, Promise.try()如果你自己沒有回復承諾, Promise.try()也會自動返回已解決的承諾。 由於第一個示例中的一條路徑無法解析或拒絕,因此這會導致兩個示例產生差異。

他們不一樣。

考慮兩個陳述都是假的情況。 在這種情況下, multiRejectExample()將永遠不會拒絕解析返回的promise,而tryExample()將“通過”並自動解析promise(值為undefined因為您不返回任何內容)。

展示:

var Promise = require('bluebird');

function test1() {
  return Promise.try(function() { });
}

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

test1().then(function() { console.log('resolved #1'); });
test2().then(function() { console.log('resolved #2'); });

這將記錄resolved #1但未resolved #2因為承諾永遠不會被實際解決(也不會被拒絕)。

以下是相同的嗎?

不,正如@robertklep已經提到過的,當statement錯誤時,它們會有不同的結果。 Promise.try捕獲異常並以函數的返回值解析,而Promise構造函數只是創建一個新的promise而不關心它何時從不resolve() d。

我什么時候應該使用哪個?

你應該使用Promise構造函數iff,並且只有當你正在使用異步回調API時才使用它 其他一切,尤其是在涉及其他承諾時 ,基本上都是反模式。
所以不要像你在問題中那樣使用它

你通常也不throw 您正在編寫一個返回promise的函數(因為它是異步的),它應該總是返回一個promise。 如果要返回因錯誤而被拒絕的承諾,可以使用Promise.reject顯式創建一個Promise.reject 因此,正確的方法是

function multiRejectExample(){ 
    if (statement){
        console.log('statement 1');
        return Promise.reject(new Error('error'));
    }
    if (statement){
        console.log('statement 2');
        return Promise.reject(new Error('error')); 
    }
    return Promise.resolve();
}

當然,這個特定的例子沒有多大意義,因為你的案例都不是異步的,根本就沒有理由使用promises。 只需使用拋出異常的同步函數。 通常情況下,你會有一些return …最后是一個實際的異步承諾,而不是一個undefined實現。

現在,如果你有這樣的功能,並且厭倦了反復編寫return Promise.reject ,你可以使用Bluebird特定的Promise.tryPromise.method方法作為語法糖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM