Try and catch around promise

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-04 06:08:18

问题


I need to write a function that returns a promise, where first I call a synchronous function A() which returns some result. Then return a function B(result) where B is a promise which takes in the result of A(). If either function fails I want the same error function C(error) to get called where C is a promise. What is the best way of writing this. This is what I have but think there is obvious way I am missing

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

It seems wrong combining synchronous try and catch with a promise .catch and also wrong there are two different places I need to call C(error).

A() throws an error rather than returning an error code.


回答1:


You don't say exactly how A() fails. It could either throw or it could return an error result. I'll show a scheme for both. The key to a mix of sync and async is to always return a promise. This will give you a consistent interface for teh caller no matter how the function succeeds or fails.

If you are only worried about A() throwing an exception and it doesn't return an error code, then you can do this:

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

If you also have the case where A() can return an error code, then you can do this:

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

Note that both of these patterns avoid creating an extra promise if it isn't needed. They only create the extra promise when returning an error that occurred synchronously.


The Bluebird promise library has a helper function for this particular circumstance called Promise.method. The utility of Promise.method() is that it automatically wraps your function in a try/catch handler and if there are any synchronous exceptions thrown, it automatically turns them into returning a rejected promise. You could use it like this:

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:


I'm assuming that both A and B can throw errors here. Using the standard API it could look like this:

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

This will return a promise that's either resolved with the output of B or the output of C, if that provides a fallback. You can also consider handling any errors outside of this function if that makes sense for your use case.

When using Bluebird this should also be possible:

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



回答3:


I think a good way to do this would be to still use promises for the synchronous function. It keeps it consistent within a function, especially if you want something to respond to the success like a pseudo-promise. But the key is that you'd use an immediately resolved promise. Take a look at this blog post on ES6 Promises.

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

assuming you've already created the promise and defined C like so:

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

this code should do what you want:

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

^ this last line is the most important, since it uses the output for A to call B



来源:https://stackoverflow.com/questions/37992756/try-and-catch-around-promise

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!