Socket.io仅适用于重新连接

时间:2018-10-03 15:29:35

标签: javascript node.js reactjs websocket socket.io

我正在构建一个连接到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 NameEmmitting Event,但浏览器似乎从未收到它(未记录receiving event)。

现在,如果我要去终端并重新启动API(无需刷新浏览器),首先我在浏览器中收到一条错误消息,说我的ws连接丢失了。 API再次开始运行后,我会看到-------- CONNECTED日志,这意味着浏览器已成功重新连接到服务器,如果再次点击change_name,现在一切正常!如果刷新浏览器,一切停止都会再次起作用,并且需要再次重新启动API。

我已经在本地和远程服务器(AWS)中对此进行了测试,其行为是相同的。第一次连接没有任何反应,重启API后浏览器自动重新连接,一切正常。

有人知道什么可能导致此行为吗?也许我在配置中缺少什么?

谢谢!

1 个答案:

答案 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() { /* ... */ }
}

但这会导致其他问题:

  1. 为什么在没有订阅的情况下,服务器重启后套接字仍可以工作?

  2. 现在问题已经解决。第一次可以正常运行,但是如果服务器重新启动,浏览器将重新连接,但不重新订阅。在浏览器重新连接后,是否可以自动重新订阅事件?

谢谢!