【问题标题】:Promises fail status承诺失败状态
【发布时间】:2015-11-13 14:32:47
【问题描述】:

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

所以我基本上做的是使用名为“失败”的状态对象进行解析,以表明它是一个失败过程,所以我发送失败消息而不是错误消息。

我做对了吗,反正上面的代码会给我错误:

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

【问题讨论】:

    标签: javascript express promise


    【解决方案1】:

    如果用户失败,您的第一个回调将返回 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 函子进行抽象可能会有所收获。

    【讨论】:

      【解决方案2】:

      您说得对,如果您需要“第三个结果”,则必须手动完成。您遇到的异常是由于您的 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 提供的解决方案也可以工作。

      【讨论】:

      • 我想我会接受这个,把失败变成拒绝。
      猜你喜欢
      • 2017-11-01
      • 2021-03-17
      • 2018-08-09
      • 1970-01-01
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 1970-01-01
      • 2020-07-30
      相关资源
      最近更新 更多