node.js - Single Instance of socket.io is recognized as multiple Sockets in Backend
问题描述
Working on a project I occured the following problem. When listening for a "startGame"-Event in the Angular-Frontend my code didn't get executed eventhough I sent a message to the correct Room in the node-Backend. To make sure I don't have multiple Sockets I created a Singleton but it didn't help and the Backend still thinks there are multiple Sockets.
This is the Code: Angular: lobby.component.ts
import {ApplicationRef, ChangeDetectorRef, Component, Inject, NgZone, OnInit} from '@angular/core';
import {switchMap} from "rxjs/operators";
import {ActivatedRoute, ParamMap, Router} from "@angular/router";
import { DOCUMENT } from "@angular/common";
import {SocketService} from "../socket.service";
import {JsonObject} from "@angular/compiler-cli/ngcc/src/packages/entry_point";
import {SpotifyService} from "../spotify.service";
@Component({
selector: 'app-lobby-component',
templateUrl: './lobby.component.html',
styleUrls: ['./lobby.component.scss']
})
export class LobbyComponent implements OnInit {
lobbyId;
lobbyinfo: any;
constructor(@Inject(DOCUMENT) public document: Document, private route: ActivatedRoute, private router: Router, private socketService: SocketService, private spotifyService: SpotifyService) {
}
ngOnInit(): void {
this.lobbyId = this.route.snapshot.paramMap.get("lobbyid");
this.socketService.joinLobby(this.lobbyId, JSON.parse(localStorage.getItem('user')).id).subscribe((info) => {
this.lobbyinfo = info;
this.socketService.waitForGameStart(this.lobbyId);
});
}
...
}
Angular: socket.service.ts
import {Injectable} from '@angular/core';
import * as io from 'socket.io-client';
import {environment} from "./environment";
import {Observable} from "rxjs";
import {JsonObject} from "@angular/compiler-cli/ngcc/src/packages/entry_point";
@Injectable({
providedIn: 'root'
})
export class SocketService {
socket;
question;
lobbyinfo;
...
getSocket() {
if(!this.socket){
this.socket = io(environment.SOCKET_ENDPOINT);
}
return this.socket;
}
joinLobby(lobbyId: string, userName: string) {
this.getSocket().emit("joinLobby", {lobbyid: lobbyId, username: userName});
this.getSocket().on('startGame', (msg) => {
//do-Stuff
//gets Executed because Socket is in the Room lobbyid
});
}
waitForGameStart(lobbyId: any) {
console.log("waitign for gamestart " + lobbyId);
//Not executed because it isn't in the lobby
this.getSocket().on('startGame', (msg) => {
//do-Stuff
//doesn't get executed even when previous call in joinLobby is commented out
});
}
}
Node: app.js
const uuidv4 = require('uuid/v4');
const express = require('express');
const app = express();
const path = require('path');
const dbConnection = require('./connections/mongoDB');
const APP_PORT = 5555;
const server = app.listen(APP_PORT, () => {
console.log(`App running on port ${APP_PORT}`);
});
dbConnection.initConnection();
const io = require('socket.io').listen(server);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static('public'));
app.get('/', (req, res) => {
res.render('index');
});
// global-Chat
io.on('connection', (socket) => {
...
socket.on('joinLobby', (msg) => {
dbConnection.updateLobbyPlayers(msg.lobbyid, msg.username).then(() => {
socket.join(msg.lobbyid);
io.in(msg.lobbyid).emit('info', msg.username + " just joined this lobby.");
});
});
socket.on('initGame', (msg) => {
...
dbConnection.startGame(msg.lobbyid, tracks, possibleTracks).then(() => {
io.in(msg.lobbyid).emit('startGame', {prepareTime: 10});
});
});
});
Note: To test the Method "waitForGameStart" I commented out the listener in "joinLobby" so the Message doesn't get catched right there.
Is there something I'm doing wrong? I feel like i don't fully understand the behaviour of sockets just yet. To me it seems like Node detects some weird differences between the two sockets and thinks they're not the same eventhough they are the same Instance.
In the worst case i'll just have to implement some kind of own "Room-Handling". Help would be appreciated, thanks
Edit: Added lobby.component.ts
Edit2: I don't get any error messages. I'm listening for messages in channel 'startGame'. I send the message with:
io.in(msg.lobbyid).emit('startGame', {prepareTime: 10});
in socket.on('initGame', ...
The problem is, that just the listener in joinLobby() gets the message. If I remove the listener in joinLobby(), the listener in waitForGameStart() still doesn't get the message. I assume that this happens, because Node recognizes both listeners as a different socket, but I'm not sure about it.
解决方案
推荐阅读
- angular - Angular ActivatedRoute,paramMap.get('id') 未按预期工作
- php - 如何在 Conatct Form 7 WP 中选中复选框
- sql - 在 SQL 中计算平均值、中位数和百分位数
- python - 根据其他列值填写空白值
- java - NoSuchBeanDefinitionException:当我使用自动配置时,没有名为“elasticsearchTemplate”的 bean 可用
- excel - 将超链接从 Excel 移动到 Word 文档并粘贴到特定范围内
- php - 链接到本地子域
- c++ - Sizeof 模板返回意外的值
- c# - 一次请求内容下载两次
- python - BeautifulSoup 返回 None 但元素确实存在