描述错误处理
学习目标
解释错误处理
为什么需要这样做?
良好的错误处理是确保给定应用程序的稳健性、正确性和性能的关键。构建健壮的应用程序需要您抛出并处理应用程序运行期间发生的异常。因此,我们将向您介绍 Node.js 中异常处理的基本概念,以及 CAP Service SDK for Node.js 的特定技术。
错误处理与错误类型
恰当的错误处理对于当今的业务应用程序至关重要。在深入细节之前,有必要区分两种类型的错误:
Programmer Errors
这些错误由编程错误导致(例如,
cannot read 'foo' of undefined
)。它们必须被修复。
Operational Errors
这些错误在运行期间发生(例如,向有故障的远程系统发送请求时)。它们必须被处理。
指导原则
“Let it crash”(让它崩溃)是源自 Erlang 编程语言(Joe Armstrong)的一种哲学,它(部分地)同样适用于 Node.js。
对于编程错误,关键要点是:
Fail loudly: 不要隐藏错误并静默继续。确保正确记录意外错误。不要捕获您无法处理的错误。
不要以防御性方式开发: 专注于您的业务逻辑,只在您知道错误会发生时才处理它们。仅在必要时使用 try/catch 块。
绝不要试图捕获和处理意外错误、Promise 拒绝等。如果它是意外的,您就无法正确处理它。如果您能处理,那它就是意料之中的(并且应该已经被处理了)。即使您的应用程序是无状态的,您也永远无法 100% 确定某个共享资源没有受到该意外错误的影响。因此,绝不允许应用程序在此类事件之后继续运行,对于存在信息泄露风险的多租户应用程序尤其如此。
遵循这些指导原则将使您的代码更短、更清晰、更简单。
绝不隐藏错误原因
发生错误时,识别根本原因至关重要。例如,CAP SDK for Node.js 在满足某些条件时会抛出异常,比如 CRUD 操作违反外键约束。在此类情况下,框架会抛出特定的异常,例如 UNIQUE_CONSTRAINT_VIOLATION。然而,如果捕获这些错误并在重新抛出时没有保留原始详细信息,追溯和解决底层问题就会变得困难。结果,最终用户只会看到一条晦涩的错误消息,使故障排除变得困难。
例如:

try {
// something
} catch (e) {
// augment instead of replace details
e.message = 'Oh no! ' + e.message
e.additionalInfo = 'This is just an example.'
// re-throw same object
throw e
}
因此,提供有意义的错误消息是有用的。
为此,您可以在服务实现中注册一个错误处理器,如下面的代码片段所示。
// Imports
constcds=require("@sap/cds");
/**
* The service implementation with all service handlers
*/
module.exports=cds.service.impl(asyncfunction(){
/**
* Custom error handler
*
* throw a new error with: throw new Error('something bad happened');
*
**/
this.on("error",(err,req)=>{
switch(err.message){
case"UNIQUE_CONSTRAINT_VIOLATION":
err.message="The entry already exists.";
break;
default:
err.message=
"An error occured. Please retry. Technical error message: "+
err.message;
break;
}
});
});
现在,只要该异常被触发,此处理器就会介入,并用替代的错误消息覆盖它:

抛出与捕获异常
您肯定会在服务中添加您的实现。您很可能希望在某个操作崩溃之前中断它。在这种情况下,您可以抛出 Node.js 异常。
请求响应
您还可以使用 req.error() 方法收集消息或错误,并在请求响应中将其返回给调用方。在此处阅读更多内容。
this.on("submitOrder",async(req)=>{
const{ book, amount }=req.data;
let{ stock }=awaitdb.read(Books,book,(b)=>b.stock);
if(stock >= amount){
awaitdb.update(Books,book).with({stock: (stock-=amount)});
awaitthis.emit("OrderedBook",{ book, amount,buyer: req.user.id});
returnreq.reply({ stock });// <-- Normal reply
}else{
// Reply with error code 409 and a custom error message
returnreq.error(409,`${amount} exceeds stock for book #${book}`);
}
});
小结
您现在已熟悉 CAP SDK for Node.js 中的核心错误处理概念。我们强烈建议采纳这些概念,以确保您的 CAP 应用程序整体上的稳健性。