尝试并捕捉承诺

时间:2016-06-23 13:15:06

标签: javascript promise bluebird

我需要编写一个返回promise的函数,首先我调用一个返回一些结果的同步函数A()。 然后返回一个函数B(结果),其中B是一个接受A()结果的promise。 如果任一函数失败,我想要调用相同的错误函数C(错误),其中C是一个promise。 写这篇文章的最佳方式是什么?这就是我所拥有的,但我认为有一种显而易见的缺失方式

function() {
    try {
        var result = A();
        return B(result)
            .catch(function(error) {
                return C(error);
            });
     }
     catch(error) {
         return C(error);
     }
}

将同步try和catch与promise .catch结合起来似乎是错误的,而且错误的是有两个不同的地方我需要调用C(错误)。

A()抛出错误而不是返回错误代码。

3 个答案:

答案 0 :(得分:2)

我假设AB都可以在这里抛出错误。使用标准API可能如下所示:

function() {
  return new Promise((resolve, reject) => {
    try {
      resolve(A());
    } catch (error) {
      reject(error);
    }
  })
  .then(B)
  .catch(C);  
}

这将返回一个承诺,该承诺可以使用B的输出或C的输出解析,如果这提供了回退。如果对您的用例有意义,您还可以考虑处理此函数之外的任何错误。

使用Bluebird时,也应该可以:

function() {
  return Promise.method(A)().then(B).catch(C)
}

答案 1 :(得分:1)

您没有确切说明A()失败的原因。它可以抛出,也可能返回错误结果。我会为两者展示一个计划。同步和异步混合的关键是始终返回一个promise。无论函数如何成功或失败,这都将为调用者提供一致的接口。

如果您只担心A()抛出异常并且它没有返回错误代码,那么您可以这样做:

function someFunction() {
    try {
        var result = A();
        return B(result);
     } catch(err) {
         return Promise.reject(err);
     }
}

someFunction().then(function(result) {
    // code here to process the final result
}).catch(C);

如果您还遇到A()可以返回错误代码的情况,那么您可以这样做:

function someFunction() {
    try {
        var result = A();
        // check for error value
        if (result < 0) {
            throw result;
        }
        return B(result);
     } catch(err) {
         return Promise.resolve(err);
     }
}

请注意,如果不需要,这两种模式都会避免产生额外的承诺。它们只在返回同步发生的错误时才创建额外的承诺。

Bluebird promise library具有针对此特定情况的辅助函数Promise.methodPromise.method()的实用程序是它自动将函数包装在try / catch处理程序中,如果抛出任何同步异常,它会自动将它们转换为返回被拒绝的promise。您可以像这样使用它:

var someFunction = Promise.method(function() {
    var result = A();
    // check for error condition
    if (result < 0) {
        throw result;
    }
    return B(result);
});

someFunction().then(function(result) {
    // code here to process the final result
}).catch(C);

答案 2 :(得分:0)

我认为这样做的好方法是仍然使用promises进行同步功能。它使它在一个函数中保持一致,特别是如果你想要像伪承诺那样响应成功。但关键是你要使用立即解决的承诺。看一下这个blog post on ES6 Promises

// an immediately resolved promise
var a = Promise.resolve(A());

假设您已经创建了承诺并定义了C,如下所示:

var B = new Promise(function(resolve, reject) {  
   if (a) {
      resolve('success');  // fulfilled successfully
   }
   else {
      C('rejected');  // error, rejected
   }
})
.then((result) => {console.log('made it!');})
.catch((result) => {C('rejected');});

var C = (err)=>{console.log('error: ' + err); return err;}

此代码应该按照您的意愿执行:

a.then((result) => B(result));

^这最后一行是最重要的,因为它使用A的输出来调用B