bluebird promise.method to wraps a function return

2019-04-21 04:16发布

问题:

using bluebird in my code , and I use promise.method to cover a original functions just like the api say.Then I write a function which return a promise,and use promise.method to cover it.Those two function return the same:

function () {
    var ret = new Promise(INTERNAL);
    ret._captureStackTrace();
    ret._pushContext();
    var value = tryCatch(fn).apply(this, arguments);
    ret._popContext();
    ret._resolveFromSyncValue(value);
    return ret;
}

Is it ok to use promise.method to cover the function return a promise??

回答1:

Building async APIs with errors

Yes, the point of Promise.method is to make methods throw safe - for example if you have a method that looks like:

function foo(jsonStr){
    var obj = JSON.parse(jsonStr);
    return getApi(obj.endpoint);
}

It might throw an error if passed an invalid object - so if you pass it an invalid string it'll throw (instead of reject). This means you have to guard against both thrown errors and rejected promises in your code and add a } catch(e){ and a .catch(function(e){ to your code.

This form of programming creates a weak and fragile API that differentiates synchronous and asynchronous errors and might (and will) create race conditions based on when errors happen. If a function might do something asynchronously it must always do it asynchronously. This is a core concept of developing asynchronous APIs - otherwise you end up with race conditions and other issues.

What Promise.method does

Promise.method basically wraps your method with a try/catch and converts thrown errors to rejections and returned values to fulfillments. If your function foo was a Promise.method it would always reject on errors instead of throwing. This fixes the race condition issue since your methods now always fail the same way.

var foo = Promise.method(function(jsonStr){
    var obj = JSON.parse(jsonStr); // if this throws - you get a rejection
    return getApi(obj.endpoint);
});

When not to use it

There are cases where you can get away with not using Promise.method - for example when your method's body is in a promise chain or you're 100% sure it won't throw. In general - I find Promise.method quite useful.

It also has the added benefit of letting you return plain values from promise returning methods and have them act consistently.

So should I wrap functions that return promises with it?

In general - yes. Exceptions apply and YMMV.