承诺失败状态

Promises fail status

本文关键字:状态 失败 承诺      更新时间:2023-09-26

承诺要么是解决,要么是拒绝,但我想有一个失败选项:

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)

如果用户失败,您的第一个回调将返回 undefined 并且您的第二个then回调仍将执行,值为 undefined 表示 user 。在 res.fail 之后调用 res.success 将导致异常,进而导致执行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 函子进行抽象中获得一些收益。

你是对的,如果你需要"第三个结果",你必须手动完成。您遇到的异常是由于您的res.success(...)代码仍在"失败"场景中执行,因为没有错误来阻止它。

做承诺时,一个好的经验法则是实现任何通常应该中断"then"流作为拒绝的条件。这意味着只要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 提供的解决方案也可以工作。