承诺失败状态

时间:2015-11-13 14:32:48

标签: javascript express promise

承诺是解决或拒绝,但我希望有一个失败选项:

users.parse(body)
.then(function (data){
    if(data.status == 'fail') {
        res.fail(data.data);
    } else {
        return users.saveUser(data.data);  
    }     
}).then(function (user) {
    res.success(merchant);
}).catch(function (err) {
    res.error(err);
});

所以我基本上做的是使用名为'fail'的状态对象来解决它是否为失败进程,因此我发送失败消息而不是错误消息。

我做得对,无论如何上面的代码都会给我错误:

Unhandled rejection Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)

2 个答案:

答案 0 :(得分:1)

如果用户失败,您的第一个回调将返回undefined,您的第二个then回调仍会被执行,undefined的值为user。在res.success之后调用res.fail将导致异常,这将导致catch回调被执行,因此它会尝试调用res.error,这会再次引发标题错误已被发送。

您应该可以使用

解决此问题
users.parse(body).then(function(data) {
    if (data.status == 'fail') {
        res.fail(data.data);
    } else {
        return users.saveUser(data.data).then(function(user) {
            res.success(merchant);
        });
    }
}).catch(function(err) {
    res.error(err);
});

然而,更清晰的解决方案是使用

users.parse(body).then(function(data) {
    if (data.status == 'fail') return data;
    else return users.saveUser(data.data);
}).then(function(user) {
    if (data.status == 'fail') 
        res.fail(data.data);
    else
        res.success(merchant);
}, function(err) {
    res.error(err);
});

使用Maybe仿函数进行抽象可能会有所收获。

答案 1 :(得分:0)

你是对的,如果你需要“第三个结果”,你必须手动完成。您遇到的异常是由于res.success(...)代码仍然在“失败”情况下执行,因为没有错误可以阻止它。

做承诺时的一个好的经验法则是实现任何通常应该中断“当时”流程作为拒绝的条件。这意味着只要users.parse拒绝输入错误,您的代码就会变成更自然的版本,所有错误都会在一个地方处理:

users.parse(body).then(function(data) {
    return users.saveUser(data.data);
}).then(function (user) {
    res.success(merchant);
}).catch(function(err) {
    if (err == 'fail') {
        res.fail(data.data)
    } else { 
        res.error(err);
    }
});

如果您决定要在“成功”分支上处理解析失败,Bergi提供的解决方案也可以正常工作。