我认为解决了以下问题的以下模式是否被视为无极反模式?
不,还好。
有更好的方法吗?
是的,看看和之间
.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));


