You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中SSE事件为空问题排查及DTO适配疑问

NestJS SSE 事件推送数据为空问题解决

问题根源

全局配置的ClassSerializerInterceptor使用了strategy: 'excludeAll'策略,会自动排除所有未通过@Expose标注的属性。而MessageEvent的data是访问器属性(getter),并非实例的可枚举自有属性,直接用plainToInstance转换时无法自动捕获该属性,导致前端拿到的event.data为空。

解决方案

方案1:手动给SSEDto赋值data属性

在映射时,先通过plainToInstance转换其他属性,再手动将MessageEvent的data赋值给SSEDto实例:

return fromEvent(this.eventEmitter, 'new-order')
  .pipe(
    map(() => {       
      const message = { hello: 'world' };
      const event = new MessageEvent('new-order', { data: message });
      const sseDto = plainToInstance(SSEDto, event);
      // 手动赋值data
      sseDto.data = event.data;
      return sseDto;
    })
  );

方案2:通过@Transform注解自动映射data

修改SSEDto,给data属性添加@Transform注解,从原始MessageEvent对象中读取data:

import { Expose, Transform } from 'class-transformer';

export class SSEDto {
    @Expose()
    @Transform(({ obj }) => obj.data) // 从MessageEvent实例中获取data
    data: string | object;

    @Expose()
    id?: string;

    @Expose()
    type?: string;

    @Expose()
    retry?: number;

    @Expose()
    defaultPrevented: boolean;

    @Expose()
    cancelable: boolean;

    @Expose()
    timeStamp: Timestamp;
}

之后直接使用plainToInstance转换即可自动获取data。

方案3:给SSE接口单独禁用全局拦截器策略

如果不想修改DTO,可以在SSE方法上添加@SerializeOptions注解,覆盖全局的excludeAll策略:

import { SerializeOptions } from '@nestjs/common';

@Sse('sse')
@SerializeOptions({
  strategy: 'default',
  excludeExtraneousValues: false,
})
sse(): Observable<MessageEvent> {
  return interval(1000).pipe(map((_) => ({ data: { hello: 'world' } }) as MessageEvent));
}

或者重新指定拦截器,使用默认策略:

import { UseInterceptors } from '@nestjs/common';
import { ClassSerializerInterceptor } from '@nestjs/common/serializer';

@Sse('sse')
@UseInterceptors(new ClassSerializerInterceptor(app.get(Reflector), {
  strategy: 'default',
}))
sse(): Observable<MessageEvent> {
  // 原有逻辑
}

内容的提问来源于stack exchange,提问作者Michał B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 01:04:52