簡體   English   中英

嵌套在 Express Router 中的 Socket.io

[英]Socket.io in deeply nested Express Router

我正在嘗試將 socket.io 實例傳遞到 Express Routes。 目前我正在設置 socket.io 服務器,如他們的文檔所示。 要將對象傳遞到我使用的路線中,我使用app.set('io', io)然后在路線中的路線const io = req.app.get('io')中。 獲得 io 對象后,我只是向所有收聽用戶發送。 這適用於第一個請求,但第二次發出相同的請求時,會向每個客戶端發送兩個事件。 第三個請求發出數據三次,依此類推。

// App.js file
//  Server imports
const app = require('express')(),
    http = require('http').Server(app),
    io = require('socket.io')(http),
    session = require('express-session');

//  Add socket.io to req for use in latter requests
app.set('io', io);

io.on('connection', (socket) => {
    console.log('User has connected to socket.io');

    socket.on('disconnect', () => {
        console.log('User has disconnected');
    });
});

//  Route Setups
app.use('/api', require('./routes'));

http.listen(process.env.PORT, () => {
    console.log(`Server running on port: ${process.env.PORT}`);
});
// Route  index.js
const router = require('express').Router();

router.use('/project', require('./project/project'));

module.exports = router;
// Project Routes
const router = require('express').Router(),
    Project = require('../../models/project');

// Route for creating new Projects
router.post('/', (req, res, next) => {
    Project.createProject(req.body.item, (err, doc) => {
        if(err) return next(err);
        res.json({_id: doc._id, projectName: doc.projectName});

        const io = req.app.get('io');
        io.emit('project', {project: {
            _id: doc._id, 
            client: doc.client,
            jobId: doc.jobId,
            projectName: doc.projectName,
            eventDate: doc.eventDate,
            dateModified: doc.dateModified,
            eventLogo: doc.eventLogo
        }});
    })
});
// index.js
// Import React Standard components
// Import and setup BrowserRouter

import App from './components/App';

import io from 'socket.io-client';
const socket = io('http://192.168.1.2:8080');


ReactDOM.render(
    <BrowserRouter>
        <App socket={socket}/>
    </BrowserRouter>
, document.getElementById('root'));


// Front End React File for displaying projects - App.js
// I cut down on some of the code to keep it simple.
import React, { Component } from 'react';

import NewProject from './NewProject';

export default class Projects extends Component {
  state = {
    projects: []
    newProject: false
  }

  closeWindow = () => {
    // Sets the state for new Project to true or false to show or hide the component 
  }

  componentDidMount = () => {
    // Fires mutiple times for each request made to update project or create new project
    this.props.socket.on('project', ({project, index}) => {
      console.log("DATA RECIEVED", project, index);
      const projects = this.state.projects;

      // If a project and index is sent, update an excising project
      if(project !== undefined && index !== undefined) {
         console.log('Project to ypdate: ',projects[index])
         projects[index] = Object.keys(projects[index]).reduce((acc, key) => {
            // Update all keys passed down from the server
         }, {});
      // If just a project is sent, add a new project
      } else if(project !== undefined && index === undefined) {
                projects.push(project);
      // If just an index is sent, remove the project
      } else if(index !== undefined) {
        const projectIndex = this.props.projects.findIndex((item) => {
          if(item._id === index) return true;
            return null;
          });
          projects.splice(projectIndex, 1);
        }
      return this.setState({projects});
    });
  }

  render() {
    return [
      this.state.newProject && <NewProject key="0" closeWindow={this.closeWindow} />
      <main key="1">
        // Display the projects
        <button type="button" onClick={this.closeWindow}>New Project</button>
      </main>
    ]
}
// Front End React File for Creating New Project
// NewProject.js
import React, { Component } from 'react';

export default class CreateProject extends Component {
  state = {
    client: '',
    projectName: '',
    jobId: '',
    eventDate: '',
    eventLogo: '',
    completeForm: false
  }

  createProject = e => {
    if(!this.state.completeForm) return;
    fetch('/api/asset/project', {
      method: 'POST',
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(this.state)
    })
    .then(res => res.json())
    .then(res => {
       return this.props.closeWindow();
    })
    .catch(error => {// Handle Error})
  }

  render() {
    return (
      <div className="popup">
        <form onSubmit={this.createProject}>
          // All inputs for form.
        </form>
      </div>
    )
  }
}

我希望每個用戶都能恢復一次發出的數據,但根據發出請求的次數,他們會多次獲得數據。

非常感謝!!

請檢查 app.js 文件被調用了多少次。 如果它被多次調用,則有 io.on("connection".. 的多個事件。因此用戶多次接收數據。

對我有用的是將它添加到 Component Will Unmount

componentWillUnmount = () => {
   this.props.socket.off('project');
}

我沒有意識到在卸載組件時事件偵聽器沒有自行分離。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM