考虑以下代码块:
getUser(userId)
.catch(function(error){
crashreporter.reportError('User DB failed', error);
// show user a generic error
})
.then(function(user) {
return chargeCreditCard(user);
})
.catch(function(error){
crashreporter.reportError('Credit card failed', error);
// show user an error saying that their credit card got rejected
})
显然,与此有关的问题是,如果用户DB失败,则将执行THEN(USER)块。另一种选择是将第一个捕获块移动到链的末尾。但是,这会引起另一个问题!我们将无法区分错误是来自用户数据库还是信用卡。
我认为解决了以下问题的以下模式是否被视为无极反模式?有更好的方法吗?我看到的问题是,您可能会陷入半回调地狱。
getUser(userId)
.then(function(user) {
return chargeCreditCard(user)
.catch(function(error){
crashreporter.reportError('Credit card failed', error);
// show user an error saying that their credit card got rejected
});
})
.catch(function(error){
crashreporter.reportError('User DB failed', error);
// show user a generic error
})
编辑:我想我还不太清楚。如果还有更多的THEN块,该怎么办,如下所示。问题在于,一旦遇到一个错误,就根本不希望链继续。
getUser(userId)
.then(function(user) {
return chargeCreditCard(user);
}, function(error){
crashreporter.reportError('User DB failed', error);
// show user a error 1
})
.then(function(chargeId) {
return saveChargeId(chargeId);
}, function(error){
crashreporter.reportError('ChargeId DB failed', error);
// show user a error 2
})
.then(function(chargeHistoryId) {
return associateChargeToUsers(chargeHistoryId);
}, function(error){
crashreporter.reportError('chargeHistoryId DB failed', error);
// show user a error 3
})
.catch(function(error){
crashreporter.reportError('Credit card failed', error);
// show user a error 4
})
我认为解决了以下问题的以下模式是否被视为无极反模式?
不,还好。
有更好的方法吗?
是的,看看和之间.then(…).catch(…)``.then(…,…)
。如果要严格区分成功案例(继续)和错误案例(报告此特定问题),则将两个回调传递给then
是一个更好的主意。这样,外部处理程序将不会由于成功案例代码中的失败而被触发,而只能由安装它的Promise中的失败触发。在您的情况下:
getUser(userId)
.then(function(user) {
return chargeCreditCard(user)
.then(function(chargeId) {
return saveChargeId(chargeId)
.then(function(chargeHistoryId) {
return associateChargeToUsers(chargeHistoryId);
.then(function(result) {
return finalFormatting(result);
}, function(error){
crashreporter.reportError('chargeHistoryId DB failed', error);
return 3;
});
}, function(error){
crashreporter.reportError('ChargeId DB failed', error);
return 2;
});
}, function(error){
crashreporter.reportError('Credit card failed', error);
return 4;
});
}, function(error){
crashreporter.reportError('User DB failed', error);
return 1;
})
.then(showToUser);
尽管您可能想使用通用错误处理程序:
getUser(userId)
.catch(function(error){
crashreporter.reportError('User DB failed', error);
throw new Error(1);
})
.then(function(user) {
return chargeCreditCard(user)
.catch(function(error){
crashreporter.reportError('Credit card failed', error);
throw new Error(4);
});
})
.then(function(chargeId) {
return saveChargeId(chargeId);
.catch(function(error){
crashreporter.reportError('ChargeId DB failed', error);
throw new Error(2);
});
})
.then(function(chargeHistoryId) {
return associateChargeToUsers(chargeHistoryId);
.catch(function(error){
crashreporter.reportError('chargeHistoryId DB failed', error);
throw new Error(3);
});
})
.then(function(result) {
return finalFormatting(result);
}, function(error) {
return error.message;
})
.then(showToUser);
在这里,每个then
回调都会返回一个承诺,该承诺会自行拒绝并产生相应的错误。理想情况下,每个被调用的函数都已经做到了,当它们没有这样做时,您需要catch
向每个函数附加一个特定的参数,您可能想使用包装器辅助函数(可能是crashreporter
?的一部分)。
function withCrashReporting(fn, msg, n) {
return function(x) {
return fn(x)
.catch(function(error){
crashreporter.reportError(msg, error);
throw new Error(n);
});
};
}
withCrashReporting(getUser, 'User DB failed', 1)(userId)
.then(withCrashReporting(chargeCreditCard, 'Credit card failed', 4))
.then(withCrashReporting(saveChargeId, 'ChargeId DB failed', 2))
.then(withCrashReporting(associateChargeToUsers, 'chargeHistoryId DB failed', 3))
.then(finalFormatting, function(error) {
return error.message;
})
.then(showToUser);
我看到的问题是,您可能会陷入半回调地狱。
不,这只是包装的适当水平。与回调地狱相反,它可以展平为最大嵌套数为2,并且始终具有返回值。
如果您绝对想避免嵌套和回调,请使用async
/ await
,尽管实际上更加难看:
try {
var user = await getUser(userId);
} catch(error) {
crashreporter.reportError('User DB failed', error);
return showToUser(1);
}
try {
var chargeId = chargeCreditCard(user);
} catch(error) {
crashreporter.reportError('Credit card failed', error);
return showToUser(4);
}
try {
var chargeHistoryId = saveChargeId(chargeId);
} catch(error) {
crashreporter.reportError('ChargeId DB failed', error);
return showToUser(2);
}
try {
var result = associateChargeToUsers(chargeHistoryId);
} catch(error) {
crashreporter.reportError('chargeHistoryId DB failed', error);
return showToUser(3);
}
return showToUser(finalFormatting(result));
问题内容: 编辑 继续重试直到承诺解决的模式(带有delay和maxRetries)。 在结果满足条件之前一直重试的模式(带有delay和maxRetries)。 具有无限重试次数(提供延迟)的高效内存动态模式。 #1的代码。 继续重试,直到承诺解决为止(该语言是否有任何改进社区?) 采用 #2的代码会 继续重试,直到条件以可重用的方式满足条件为止(条件会有所不同)。 问题答案: 有点不同… 异步
问题内容: 我正在尝试用正确的方法表示正确的方法,以指示内发生故障。 如果诺言没有失败,(即返回诺言的操作是否正常工作,例如返回状态200的AJAX请求),但是我认为结果无效,通常我会这样做弹出窗口,向用户说明问题,然后执行“返回假”;尽早退出该方法。 但是,有了承诺,如果我想从.then()内部做类似的事情,我就被引导去相信我应该做的是抛出一个错误,而应该让它被.catch()抓住。 ),我已经
问题内容: 问题1:在给定的时间只允许一个API请求,因此,真正的网络请求在尚未完成的情况下排队。应用可以随时调用API级别,并且期望得到回报。当API调用排入队列时,将在将来的某个时刻创建对网络请求的承诺- 返回什么给应用程序?这样可以通过延迟的“代理”承诺来解决: 问题2:对一些API调用进行反跳动,以便随着时间的推移累积要发送的数据,然后在达到超时时分批发送。调用API的应用期望得到回报。
问题内容: 我已经在多个地方阅读了诺言处理程序模式,但我不知道它是什么。建议我在如下代码中使用它: 什么是Proposal Disposer模式,在这里如何应用? 注意-在本机的Promise中,我做为“添加返回值但执行操作的拒绝和实现处理程序”。在这种情况下,我会使用蓝鸟。 问题答案: 您的代码有问题 上述方法的问题在于,如果您在每次执行操作后都忘记释放连接,则可能会导致资源泄漏,当应用程序耗尽
问题内容: 我对诺言不太熟悉。我想从承诺电话中隐藏承诺的实现。 例: 然后我将在同一文件中而不是在同一函数中解决我的诺言,我称其为诺言。 现在,我知道“ promiseFriend”是不确定的。我如何才能将承诺电话与承诺解决方案区分开? 问题答案: 如果要在函数中定义一个promise并在其他地方使用它,则首先需要从该函数返回promise,而您在代码中没有这样做。然后,您需要实际调用您也没有执行
问题内容: 因此,我希望我的第一级捕获是处理错误的捕获。反正有没有将我的错误传播到第一个陷阱? 参考代码,尚不可用: 问题答案: 使用新的异步/等待语法,您可以实现此目的。请注意,在编写本文时,并非所有浏览器都支持此功能,您可能需要使用babel(或类似的东西)来转换代码。