尝试抓住承诺

Try and catch around promise

我需要编写一个 return 是一个承诺的函数,首先我调用一个同步函数 A(),它 return 是一些结果。 然后 return 一个函数 B(result),其中 B 是一个接受 A() 结果的承诺。 如果任一函数失败,我希望在 C 是一个承诺的地方调用相同的错误函数 C(error) 。 写这个的最好方法是什么。这就是我所拥有的,但我认为我很明显地错过了

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

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

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

我假设 AB 都会在此处抛出错误。使用标准 API 它可能看起来像这样:

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

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

使用 Bluebird 时,这应该也是可能的:

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

你没有说清楚 A() 是如何失败的。它可以抛出或 return 一个错误结果。我将展示两者的方案。同步和异步混合的关键是始终 return 一个承诺。这将为调用者提供一致的接口,无论函数如何成功或失败。

如果您只担心 A() 抛出异常而不会 return 错误代码,那么您可以这样做:

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()可以return错误代码的情况,那么你可以这样做:

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

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


Bluebird promise library 有一个针对这种特殊情况的辅助函数,称为 Promise.methodPromise.method() 的效用在于它会自动将您的函数包装在 try/catch 处理程序中,如果抛出任何同步异常,它会自动将它们变成 returning 被拒绝的承诺。你可以这样使用它:

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);

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

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

假设您已经创建了 promise 并像这样定义了 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