【问题标题】:Bluebird Promise Chains: 'Catch' with ResultBluebird Promise Chains: 'Catch' with Result
【发布时间】:2015-09-30 14:07:02
【问题描述】:

为了使这个问题对尽可能多的人有用,我将排除我的具体实现细节,除了我在下面使用带有 Node + Express 的 Bluebird Promise 库。

所以,假设我有以下链(P 返回一个承诺,res 是 Express HTTP 响应对象):

P().then(function(){
    // do nothing if all went well (for now)
    // we only care if there is an error
}).catch(function(error){
    res.status(500).send("An error occurred");
}).then(function(){
    return P();
}).then(function(pVal1){
    return [pVal1, P()];
}) // TODO: catch an error from P() here and log pVal1
.spread(function(pVal1, pVal2){
    if(pVal1 === pVal2) {
        console.log("Success!");
    } else {
        console.log("Failure");
    }
});

我在上面放置TODO 注释的位置是我想捕捉调用P 时可能发生的错误的位置。如果我确实捕获了一个错误,我想记录pVal1,然后发送一个 500 错误,就像在第一次捕获中所做的那样。但是,我不确定我如何构建我的链是否可能。

我认为我需要做一些“分支”,但我认为我对这个概念的理解还不够好,无法阻止 JavaScript 的异步特性发挥最大作用!因此,非常感谢任何帮助。

【问题讨论】:

  • 如果我完全做错了,请告诉我!
  • @torazaburo 不,不是。
  • @BenjaminGruenbaum 为什么不呢?
  • @DavidKnipe 参数 - Promise.resolve("HI").then(alert);Promise.resolve("HI").then(function(){ return alert(); });
  • 我假设你说function() { return alert(); } 忽略了它的论点。这是真实的。但在这个问题中,P 似乎无论如何都忽略了它的论点。如果是,那么function() { return P(); } 等价于P

标签: javascript node.js promise bluebird


【解决方案1】:

如果您使用显式 Promise.all 而不是将数组返回到 .spread,这是可能的。

}).then(function(pVal1){
    // this becomes a `Promise.all` - the aggregation is explicit
    var all = Promise.all([pVal1, P()]);
    all.catch(function(e){  // "branching", we both return and `catch` the promise
        console.log("Error, pVal1 is", pVal1);
    });
    return all; // return it
}).spread(function(pVal1, pVal2){
       // ....
});

【讨论】:

  • 这种代码不会导致“未处理的拒绝”吗?
  • 好的,我做到了,是的,它确实记录了未处理的拒绝(我的预感是正确的,尽管我仍然不完全理解“未处理”的条件)。但我们想要吗?
【解决方案2】:

不要忘记在链的末尾捕获错误。这也是发送响应的地方。

在链的中间捕获错误用于间歇性错误处理;链继续运行,所以暂时不要发送响应。

这里有一些东西可以试试:

// example middleware
function handle(req, res, next) {
    log("----------------");
    return async("p1", "foo").then(function (pVal1) {
        return pVal1;
    }).then(function (pVal1) {
        var p2a = async("p2a", "bar"),
            p2b = async("p2a", "bar").catch(function (error) {
                log("Logging: " + error + " (pVal1 " + pVal1 + ")");
            });
        return [p2a, p2b];
    }).spread(function (pVal1, pVal2) {
        if (pVal1 === pVal2) {
            res.send("Success!");
        } else {
            res.send("Failure");
        }
    }).catch(function (error) {
        res.status(500).send("An error occurred");
        log("Logging: " + error);
    });
}

// ---------------------------------------------------------------------
// mockup response object
var res = {
    status: function (code) {
        log("Sending status: " + code);
        return this;
    },
    send: function () {
        log("Sending response: " + [].join.call(arguments, " "));
        return this;
    }
};

// mockup promise generator
function async(name, value) {
    return new P(function (resolve, reject) {
        if ( confirm("let " + name + " succeed?") ) {
            log(name + " succeeds...");
            resolve(value);
        } else {
            log(name + " fails...");
            reject(name + " has failed");
        }
    });
}

function log() {
     var msg = document.createElement("DIV");
     msg.textContent = [].join.call(arguments, " ");
     document.getElementById("log").appendChild(msg)
     document.body.scrollTop = document.body.scrollHeight;
}
button {
    position: fixed;
    top: 5px;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.33/bluebird.min.js"></script>

<button onclick="handle(null, res, null)">Go</button>

<div id="log"></div>

【讨论】:

  • 啊,catch 内的 then 可能是我所缺少的。我什至没有想过以这种方式构建它。该示例也使这成为一个很好的答案!
猜你喜欢
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
  • 2018-04-18
  • 2016-07-08
相关资源
最近更新 更多