首页 > 解决方案 > Socket io 为同一个客户端多次发射

问题描述

我正在开发一个聊天应用程序,前端使用 angular 5,后端使用 nodeJS,使用 mongoDB 存储数据。我集成了socket io来实时发出消息

以下是我用来开发应用程序的代码。现在,当用户在文本框中触发消息时,我仅将消息发送给接收消息的用户。例如,如果 user1 正在向 user2 发送消息,则只有 user2 获得套接字事件,而不是所有其他连接的用户。所以我找到了一种使用 socket.id 向特定用户发射的方法

我没有使用相同的路由来呈现所有用户,我对不同的用户使用不同的路由,比如“John”是登录用户,用户可以在 /message/ABC、/message/ 中与其他用户聊天XYZ 等。

客户端 :

聊天组件.ts

ngOnInit() {
    this.loggedInUser = this.authService.getLoggedInUser();

    this.route.params
      .subscribe(params => {
        this.username = params['username'];
        this.receiveMessage();
      });
  }

sendMessage(message) {
    const messageDetails = {
      fromUsername : this.loggedInUser.username,
      message      : (message).trim(),
      toUsername   : this.username
    };

    this.socketService
      .sendMessage(messageDetails);
  }

  receiveMessage() {
    this.socketService
      .receiveMessage()
      .subscribe(
        (message : Message) => {
          console.log(message);
      });
  }

socket.service.client.ts

import * as io from 'socket.io-client';


private BASE_URL = AppConstants.ApiEndPoint.socketUrl;
private socket;

constructor() {
  this.socket = io("http://localhost:3000/");
}


sendMessage(messageDetails) {
    this.socket.emit('addMessage', messageDetails);
  }

  receiveMessage() {
    return new Observable(observer => {
      this.socket.on('addMessageResponse', function (message) {
        observer.next(message);
      });
      return () => {
        this.socket.disconnect();
      };
    });
  }

服务器端 :

服务器.js

我使用 express 作为中间件并将服务器实例传递到服务器端的套接字

const http       = require('http');
const app        = express();
const server = http.createServer(app);

require("./server/services/socket.service.server")(server);

server.listen(port);

Socket.service.server.js

在套接字事件addMessage上,我将消息添加到我的数据库中,然后从我的用户模型呈现 toUser 的 socketId ,因此仅向预期用户发出。

module.exports = function (server) {

  var socketIo     = require('socket.io');
  var userModel    = require("../models/user/user.model.server");
  var messageModel = require("../models/message/message.model.server");

  const io = socketIo(server);

  io.on('connection', function(socket) {

    socket.on('addMessage', function (messageDetails) {
      messageModel
        .createMessage(messageDetails)
        .then(function (message) {
          userModel
            .findUserByUsername(message.toUsername)
            .then(function (user) {
              var socketId = user.socketId;
              io.to(socketId).emit('addMessageResponse', message);
            });
        });
    })

  });
};

现在消息被发送到客户端给特定的用户。这很好用,但我收到的消息是用户连接到客户端的次数。

例如,我使用用户PO登录,我在路由 /chat/ok 上,其中 ok 是已连接的用户,ok 向 po 发送消息。PO在控制台收到消息如下

截图 1

现在我正在导航以与另一个用户聊天,并且我在 /chat/kk 路线上,其中 kk 是另一个连接的用户。

现在,如果 kk 向 po 发送消息,我会收到两次消息。正如您在下面看到的,我导航到 /chat/kk ,我收到了两次消息。同样,如果我导航到另一个用户,我会收到三次消息,依此类推。Socket io 根据用户连接到套接字的次数向用户发出消息。

截图 2

我只想要聊天应用程序的正常工作流程,而不是多次发送用户连接到客户端的消息。有解决方法吗?我想当我收到响应或者我为同一个客户端连接多次时,我在客户端回调中犯了错误。有人可以帮帮我吗。

谢谢 !

标签: javascriptnode.jssocket.ioangular5

解决方案


当您将其描述为全局变量时,socket.io 不正确
您错误的原因是代码

constructor() {
  this.socket = io("http://localhost:3000/");
}

您在 receiveMessage 函数内部删除和定义。它必须正常工作。


推荐阅读