Socket.io работает только на переподключение - PullRequest
0 голосов
/ 03 октября 2018

Я создаю приложение 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.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() { /* ... */ }
}

Теперь,дело в том, что я могу заставить эту работу работать, только если веб-приложение повторно подключается к веб-сокету.Для иллюстрации:

Когда приложение и API работают, я нажал на localhost: 8888 в своем браузере, чтобы получить доступ к приложению.API успешно регистрирует ------ CONNECTED, и я не вижу никаких ошибок на вкладке сети моего браузера, поэтому я предполагаю, что соединение работает нормально.Но потом, когда я вхожу в маршрут /change_name, ничего не происходит.API регистрирует как Change Name, так и Emmitting Event, но браузер, кажется, никогда его не получает (receiving event не зарегистрировано).

Теперь, если я перехожу к своему терминалу, перезапустите мой API (без обновлениябраузер), сначала я получаю сообщение об ошибке в браузере, в котором говорится, что мое соединение ws потеряно.Как только API снова запускается, я вижу журнал -------- CONNECTED, означающий, что браузер успешно переподключен к серверу, и если я снова нажму change_name, теперь все работает нормально!Если я обновляю браузер, все перестает работать снова, и мне нужно перезапустить мой API.

Я проверил это как на локальном, так и на удаленном сервере (AWS), и поведение остается тем же.При первом соединении ничего не происходит, после перезапуска API и автоматического переподключения браузера все работает нормально.

Кто-нибудь знает, что может быть причиной такого поведения?Может я что-то упускаю в конфигурации?

Спасибо!

1 Ответ

0 голосов
/ 03 октября 2018

Как отметил Стив в комментариях, этот учебник объясняет, как правильно реализовать 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() { /* ... */ }
}

Но это приводит к другим вопросам:

  1. Почему без подписки сокет работал после перезапуска сервера?

  2. Теперь проблема перевернулась.Он работает нормально с первого раза, но если сервер перезагружается, браузер переподключается, но не переподписывается.Есть ли способ автоматически повторно подписаться на событие после повторного подключения браузера?

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...