Mikro ORM验证错误未被捕获,Socket请求挂起如何修复?
修复方案
核心问题分析
- 异步操作未加
await:原代码中this.em.persistAndFlush(created)没有添加await,导致该异步操作的错误无法被当前try/catch捕获,Promise会在try块外部拒绝,这是错误未被捕获的核心原因。 - 未处理
ValidationError:当前catch块仅处理了NotFoundError,未覆盖ORM验证抛出的ValidationError。 - Socket异常传递错误:直接抛出HTTP风格异常(如
NotFoundException)无法在Socket上下文正确传递,导致请求挂起。
具体修复代码
@SubscribeMessage('sendMessage') async handleSendMessage( client: Socket, payload: CreateMessageInput, ): Promise<void> { // 提前拦截必填参数缺失的情况 if (!payload.userId) { client.emit('sendMessageError', 'User ID is required.'); return; } try { const created = this.em.create(Chat, { text: payload.text, user: payload.userId, }); // 给异步操作添加await,确保错误能被try/catch捕获 await this.em.persistAndFlush(created); const { userName } = await this.em.findOneOrFail(User, { id: payload.userId, }); this.server.emit('receiveMessage', { text: payload.text, user: { userName, id: payload.userId }, }); } catch (e) { // 根据错误类型返回对应提示,通过自定义错误事件传递给客户端 if (e.name === 'NotFoundError') { client.emit('sendMessageError', 'User not found.'); } else if (e.name === 'ValidationError') { client.emit('sendMessageError', 'Invalid message data: user is required.'); } else { client.emit('sendMessageError', 'Something went wrong'); } } }
关键优化点
- 添加
await捕获异步错误:给persistAndFlush添加await,确保ORM操作的错误能进入try/catch流程。 - 提前参数验证:在ORM操作前先检查
payload.userId是否存在,避免触发ORM的验证逻辑,减少不必要的数据库交互。 - Socket错误事件传递:通过自定义错误事件(如
sendMessageError)将错误信息发送给发起请求的客户端,替代HTTP风格异常,避免请求挂起。 - 覆盖
ValidationError处理:在catch块中识别ValidationError类型,返回明确的错误提示。
内容的提问来源于stack exchange,提问作者Bowis
相关产品推荐
相关产品推荐

