有没有一种方法可以结合Bluebird的`then`和`catch`功能?

Dom*_*omi 1 javascript promise bluebird

鉴于,我有一些像这样的代码:

// code bits to be executed
var X = ...;
var pre = ...;
var success = ...;
var error = ...;
var post = ...;
Run Code Online (Sandbox Code Playgroud)

我会像这样用Bluebird运行它:

X
.then(function(val) {
    pre(val);
    success(val);
    post(val);
})
.catch(function(err) {
    pre();
    error(err);
    post();
});
Run Code Online (Sandbox Code Playgroud)

我正在寻找更简单的东西(在那里,我可以定义更少的functions),沿着这样的方向:

X
.complete(function(err, val) {
    pre(val);
    if (err) {
        error(err);
    }
    else {
        success(val);
    }
    post(val);
});
Run Code Online (Sandbox Code Playgroud)

请注意,我无法使用finally,因为它没有参数,也err没有val.另请注意,val假设是nullundefined出现错误.

PS:我想的越多,我就越觉得CoffeeScript可以修复冗长问题,同时保持整洁干净(保持if外观并保持"可链接")......

Ben*_*aum 5

是的你可以

你可以走出一个承诺链回到回调土地,nodeify这会使一个节点错误回复,如:

.nodeify(function(err, val) {
    pre(val);
    if (err) {
        error(err);
    }
    else {
        success(val);
    }
    post(val);
});
Run Code Online (Sandbox Code Playgroud)

这对于需要公开类似接口的节点错误的代码非常有用.

但你可能不应该这样做

但是,我不认为在这里使用.nodeify是一个非常好的主意 - 而是你可以这样做:

.finally(pre) // you always need this
.then(success, error) // call success and error and recover
.then(post); // post, this requires that `success` also returns val 
Run Code Online (Sandbox Code Playgroud)

一般情况下,你希望有一个成功/失败的功能-这就是所谓.then(success, fail)反模式,并指出您应该考虑重组你的代码拥抱的承诺.

回报承诺

一般情况下,您可以返回承诺,而不是像您的示例中那样获取成功和错误回调 - 所以如果您的函数是:

function doStuff(success, error){
    x().then(moreStuff).then(success, error)
}
Run Code Online (Sandbox Code Playgroud)

你使用它像: doStuff(success, error)

你可以把它写成:

function doStuff(){
    return x().then(moreStuff)
}
Run Code Online (Sandbox Code Playgroud)

然后使用它doStuff().then(...)可以更容易地链接,聚合和操纵承诺.

处理器模式

前/后的常见模式是处理器模式 - 例如"pre"打开数据库连接,"post"关闭数据库连接.这可以表示为:

function withHandle(fn){
    var handle;
    return pre().then(function(resource){ // obtain the resource
       handle = resource; // keep a handle
       return resource;
    }).
    then(fn). // run the actual code for that resource
    finally(function(){
       return handle.close(); // close the resource
    });
}
Run Code Online (Sandbox Code Playgroud)

然后使用像:

withHandle(function(handle){
     return handle.query("Give me the first user"); 
}).then(function(result){
    // access result here, the handle is closed, can attach `catch`
});
Run Code Online (Sandbox Code Playgroud)