Bluebird.JS承诺:新Promise(函数(解析,拒绝){})vs Promise.try(function(){})

时间:2015-08-21 19:53:34

标签: javascript promise bluebird

我什么时候应该使用哪个?以下是相同的吗?

新的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'); 
   }
  });
}

3 个答案:

答案 0 :(得分:8)

在这种情况下,你可以主要使用(有一个行为差异)。第一个是标准承诺功能,可以与任何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.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()也会自动返回已解决的承诺。由于您的第一个示例中的一条路径无法解析或拒绝,因此这会导致您的两个示例产生差异。

答案 1 :(得分:3)

他们不一样。

考虑两个陈述都是假的情况。在这种情况下,multiRejectExample()永远不会拒绝来解决已退回的承诺,而tryExample()将会"通过"并自动解决承诺(价值为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,因为承诺永远不会被解决(也不会被拒绝)。

答案 2 :(得分:3)

  

以下是否相同?

没有。正如@robertklep已经提到的,当statement为假时,它们会有不同的结果。 Promise.try捕获异常,否则使用函数的返回值进行解析,而Promise构造函数只是创建一个新的promise,而不关心它是什么时候resolve() d。

  

我什么时候应该使用哪个?

您应该使用Promise构造函数iff,而仅在时使用promisifying an asynchronous callback API。其他一切,特别是when involving other promises,基本上都是反模式 所以不要像你在问题中那样使用它

您通常也不会throw。您正在编写一个返回promise的函数(因为它是异步的),它应该总是返回一个promise。如果要返回因错误而被拒绝的承诺,您可以使用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方法作为语法糖< / em>的