Я создаю приложение React, которое подключается к API Nodejs, и пытаюсь реализовать библиотеку 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.info("------------------------- CONNECTED!!!");
app.get('/change_name', (req, res) => {
console.info("Change Name");
const { name } = req.query;
res.sendStatus(200);
console.info('Emitting Event');
socket.emit('name', name);
});
});
server.listen(port, err => err ? throw err : console.info("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.info("Open Socket");
const socket = openSocket('http://localhost:3300', {
transports: [ 'websocket', 'polling' ],
});
console.info("Set event listener");
socket.on('name', name => {
console.info('receiving event')
this.setState({ name });
});
}
render() { /* ... */ }
}
Дело в том, что я могу заставить эту работу работать, только если веб-приложение повторно подключится к веб-сокету. Проиллюстрировать:
Запустив приложение и API, я нажимаю localhost: 8888 в своем браузере, чтобы получить доступ к приложению. API успешно регистрирует ------ CONNECTED, и я не вижу никаких ошибок на вкладке сети в моем браузере, поэтому я предполагаю, что соединение работает нормально. Но потом, когда я попадаю в маршрут /change_name, ничего не происходит. API регистрирует как Change Name, так и Emmitting Event, но браузер, кажется, никогда не получает его (receiving event не регистрируется).
Теперь, если я перейду на свой терминал и перезапущу свой API (без обновления браузера), сначала я получаю сообщение об ошибке в браузере о том, что мое ws-соединение было потеряно. Как только API снова запускается, я вижу журнал -------- CONNECTED, что означает, что браузер успешно переподключился к серверу, и если я снова нажму change_name, теперь все работает нормально! Если я обновлю браузер, все снова перестанет работать, и мне нужно снова перезапустить свой API.
Я тестировал это как на локальном, так и на удаленном сервере (AWS), и поведение было одинаковым. При первом подключении ничего не происходит, после перезапуска API и автоматического переподключения браузера все работает нормально.
Кто-нибудь знает, что могло вызвать такое поведение? Может мне что-то не хватает в конфигурации?
Спасибо!
Стив, это был именно тот учебник, которому я следовал, но я не понимаю, почему я удалил часть подписки = S (хотя я заставил ее работать без нее в первый раз). Добавление подписки действительно решило мою проблему. Я уточню в ответе.
Я рад, что он решил это за вас.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Как Стив указал в комментариях, в руководстве по это объясняется, как правильно реализовать 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.info("------------------------- CONNECTED!!!");
socket.on('subscribeToName', () => { // <---- add this
app.get('/change_name', (req, res) => {
console.info("Change Name");
const { name } = req.query;
res.sendStatus(200);
console.info('Emitting Event');
socket.emit('name', name);
});
});
});
server.listen(port, err => err ? throw err : console.info("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.info("Open Socket");
const socket = openSocket('http://localhost:3300', {
transports: [ 'websocket', 'polling' ],
});
console.info("Set event listener");
socket.on('name', name => {
console.info('receiving event')
this.setState({ name });
});
console.info("Subscribe to Listener");
socket.emit('subscribeToName'); // <---- add this
}
render() { /* ... */ }
}
Но это приводит к другим вопросам:
Почему без подписки сокет работал после перезапуска сервера?
Теперь проблема перевернулась. В первый раз он работает нормально, но если сервер перезагружается, браузер снова подключается, но не подписывается повторно. Есть ли способ автоматически повторно подписаться на событие после переподключения браузера?
Спасибо!