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

NestJS后端向RTK Query前端推送通知失败:Socket监听无响应排查

问题描述

我希望在用户收到关注请求时向其推送通知。目前后端控制台已能显示通知消息,但前端Socket无法监听到通知。

相关代码

前端RTK Query配置

import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "./config";
import { io } from "socket.io-client";

export const user = createApi({
  endpoints: (builder) => ({
    getNotifications: builder.query({
      queryFn: () => {
        return {
          data: []
        }
      },
      async onCacheEntryAdded(
        arg, {
          updateCachedData,
          cacheDataLoaded,
          cacheEntryRemoved
        }
      ) {
        try {
          await cacheDataLoaded;

          const socket = io('http://localhost:8000', {
            withCredentials: true,
          });

          // 假设当前用户ID已通过认证获取,比如从redux store或auth上下文
          const currentUserId = '当前用户的ID'; // 替换为实际获取方式
          socket.emit('joinRoom', currentUserId);

          // 监听通知,修正参数类型
          socket.on("notifications", (message) => {
            updateCachedData((draft) => {
              draft.push(message);
            });
          });

          await cacheEntryRemoved;
          socket.disconnect();
        } catch (err) {
          console.error('Socket连接或监听出错:', err);
        } finally {
          await cacheEntryRemoved;
        }
      },
    }),
  }),
});

后端followRequest.service代码

async acceptFollowRequest(requestId: string) {
  // 此处省略获取senderId和receiverId的逻辑

  // 创建关注关系:发送者关注接收者
  await this.prisma.follower.create({
    data: {
      followerId: senderId,
      followingId: receiverId,
    },
  });

  this.notificationsGateway.sendNotification({
    message: `你的关注请求已被用户 ${receiverId} 接受`,
    userId: senderId,
  });
}

后端notification.gateway代码

import {
  WebSocketGateway,
  WebSocketServer,
  OnGatewayConnection,
  OnGatewayDisconnect,
  SubscribeMessage,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

@WebSocketGateway({
  cors: {
    origin: process.env.FRONTEND_URL,
    credentials: true,
  },
})
export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer() server: Server;

  handleConnection(client: Socket) {
    // 可在此处从客户端连接信息中获取用户ID,比如cookie、token等
    // 示例:假设从auth token解析userId
    // const userId = client.handshake.auth.userId;
    // 如果需要验证用户,可在此处处理
    console.log(`客户端 ${client.id} 已连接`);
  }

  handleDisconnect(client: Socket) {
    console.log(`客户端 ${client.id} 已断开连接`);
  }

  // 处理前端加入房间的请求
  @SubscribeMessage('joinRoom')
  handleJoinRoom(client: Socket, userId: string) {
    client.join(userId);
    console.log(`客户端 ${client.id} 加入房间:${userId}`);
  }

  sendNotification(notification: { message: string; userId: string }) {
    this.server
      .to(notification.userId)
      .emit('notifications', notification.message);
    console.log(notification.message);
  }
}
问题排查与修复要点
  • 房间订阅缺失:后端通过to(notification.userId)向指定房间发送消息,但前端未加入该用户ID对应的房间。需在前端连接Socket后,发送joinRoom事件传入当前用户ID,后端接收后让客户端加入对应房间。
  • 前端监听冗余与类型错误:原代码中两次监听notifications事件,且第二个监听的参数类型错误(Socket.io回调直接返回数据,而非MessageEvent),需移除冗余监听并修正参数处理。
  • 资源清理:在cacheEntryRemoved后断开Socket连接,避免内存泄漏。
  • 用户身份关联:确保后端能正确识别每个连接的用户身份,将Socket连接与用户ID绑定,才能精准推送通知到目标用户。

内容的提问来源于stack exchange,提问作者Damilola Adegbemile

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:37:29