Bluebird Promise Chains: 'Catch' with Result
Posted
技术标签:
【中文标题】Bluebird Promise Chains: \'Catch\' with Result【英文标题】: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
。
【参考方案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
可能是我所缺少的。我什至没有想过以这种方式构建它。该示例也使这成为一个很好的答案!以上是关于Bluebird Promise Chains: 'Catch' with Result的主要内容,如果未能解决你的问题,请参考以下文章
非 Promise 值的“等待”无效(Bluebird 承诺)
Bluebird Promise.all - 多个 Promise 完成聚合成功和拒绝