错误
抛出的错误会连同其所有信息(如错误消息和堆栈跟踪)自动转发到客户端。
如果错误对象的名义实例很重要(因为你使用了 instanceof),则需要使用 @entity.name('@error:unique-name')
,以便在运行时注册并复用给定的错误类。
@entity.name('@error:myError') class MyError extends Error {} // 服务器 @rpc.controller('/main') class Controller { @rpc.action() saveUser(user: User): void { throw new MyError('Can not save user'); } } // 客户端 // [MyError] 确保在运行时已知 MyError 类 const controller = client.controller<Controller>('/main', [MyError]); try { await controller.getUser(2); } catch (e) { if (e instanceof MyError) { // 哎呀,无法保存用户 } else { // 所有其他错误 } }
转换错误
由于抛出的错误会连同其所有信息(如错误消息和堆栈跟踪)自动转发到客户端,这可能会意外泄露敏感信息。要改变这一点,可以在 transformError
方法中对抛出的错误进行修改。
class MyKernelSecurity extends RpcKernelSecurity { constructor(private logger: Logger) { super(); } transformError(error: Error) { // 包装为新的错误 this.logger.error('Error in RPC', error); return new Error('Something went wrong: ' + error.message); } }
请注意,一旦错误被转换为通用的 error
,完整的堆栈跟踪和错误的身份将会丢失。因此,客户端无法对该错误使用 instanceof
检查。
如果 Deepkit RPC 用于两个微服务之间,因此客户端和服务器都由开发者完全控制,那么通常很少需要转换错误。另一方面,如果客户端在浏览器中运行且面向未知用户,则应在 transformError
中谨慎决定要披露的信息。若有不确定,应将每个错误都转换为通用的 Error
,以确保不会泄露任何内部细节。在此情况下记录错误日志是个好主意。