我正在构建一个连接到Nodejs API的React应用程序,并且正在尝试实现Socket.io库。我遵循了互联网上的一些教程,现在我的代码如下:
API:
import express from 'express';
import socketIo from 'socket.io';
import http from 'http';
const app = express();
const port = 3300;
const server = http.createServer(app);
const io = socketIo({
serveClient: false,
transports: [ 'websocket', 'polling' ],
pingTimeout: 3000,
pingInterval: 3000,
allowUpgrades: false,
upgrade: false,
cookie: false
}).listen(server);
io.on('connection', function(socket){
console.log("------------------------- CONNECTED!!!");
app.get('/change_name', (req, res) => {
console.log("Change Name");
const { name } = req.query;
res.sendStatus(200);
console.log('Emitting Event');
socket.emit('name', name);
});
});
server.listen(port, err => err ? throw err : console.log("Server online. Listening to port " + port);
在我的React应用中:
import React from "react";
import openSocket from 'socket.io-client';
export default class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "Thiago"
};
console.log("Open Socket");
const socket = openSocket('http://localhost:3300', {
transports: [ 'websocket', 'polling' ],
});
console.log("Set event listener");
socket.on('name', name => {
console.log('receiving event')
this.setState({ name });
});
}
render() { /* ... */ }
}
现在,问题是,只有在Web应用程序与websocket重新连接时,我才能使此工作正常。为了说明:
运行我的应用程序和API后,我在浏览器中点击localhost:8888以访问该应用程序。 API成功记录了------ CONNECTED
,并且在浏览器的“网络”标签中看不到任何错误,因此我猜想连接工作正常。但是,当我打/change_name
路线时,什么也没发生。该API会同时记录Change Name
和Emmitting Event
,但浏览器似乎从未收到它(未记录receiving event
)。
现在,如果我要去终端并重新启动API(无需刷新浏览器),首先我在浏览器中收到一条错误消息,说我的ws连接丢失了。 API再次开始运行后,我会看到-------- CONNECTED
日志,这意味着浏览器已成功重新连接到服务器,如果再次点击change_name
,现在一切正常!如果刷新浏览器,一切停止都会再次起作用,并且需要再次重新启动API。
我已经在本地和远程服务器(AWS)中对此进行了测试,其行为是相同的。第一次连接没有任何反应,重启API后浏览器自动重新连接,一切正常。
有人知道什么可能导致此行为吗?也许我在配置中缺少什么?
谢谢!
答案 0 :(得分:0)
正如史蒂夫(Steve)在评论中指出的那样,this教程介绍了如何正确实现socket.io。
好像我缺少订阅部分。当我添加它时,一切开始起作用。现在的代码是这样的:
API:
import express from 'express';
import socketIo from 'socket.io';
import http from 'http';
const app = express();
const port = 3300;
const server = http.createServer(app);
const io = socketIo({
serveClient: false,
transports: [ 'websocket', 'polling' ],
pingTimeout: 3000,
pingInterval: 3000,
allowUpgrades: false,
upgrade: false,
cookie: false
}).listen(server);
io.on('connection', function(socket){
console.log("------------------------- CONNECTED!!!");
socket.on('subscribeToName', () => { // <---- add this
app.get('/change_name', (req, res) => {
console.log("Change Name");
const { name } = req.query;
res.sendStatus(200);
console.log('Emitting Event');
socket.emit('name', name);
});
});
});
server.listen(port, err => err ? throw err : console.log("Server online. Listening to port " + port);
在我的React应用中:
import React from "react";
import openSocket from 'socket.io-client';
export default class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "Thiago"
};
console.log("Open Socket");
const socket = openSocket('http://localhost:3300', {
transports: [ 'websocket', 'polling' ],
});
console.log("Set event listener");
socket.on('name', name => {
console.log('receiving event')
this.setState({ name });
});
console.log("Subscribe to Listener");
socket.emit('subscribeToName'); // <---- add this
}
render() { /* ... */ }
}
但这会导致其他问题:
为什么在没有订阅的情况下,服务器重启后套接字仍可以工作?
现在问题已经解决。第一次可以正常运行,但是如果服务器重新启动,浏览器将重新连接,但不重新订阅。在浏览器重新连接后,是否可以自动重新订阅事件?
谢谢!