我正在尝试将Socket.IO与我的应用程序集成。我正在构建一个实时数据工具。现在,我只想看到我的服务器和客户端之间的持续通信。我想发送一条简单的消息,并每隔5秒在控制台上记录一次。
这是我的server.js:
const path = require('path');
const express = require('express');
const http = require("http");
const socketIo = require("socket.io");
const DIST_DIR = path.join(__dirname, 'public/');
const PORT = 3000;
const app = express();
app.use(express.static(DIST_DIR));
const server = http.createServer(app);
//wire up ExpressJS server to Socket.IO
const io = socketIo(server);
io.on("connection", (socket) => {
console.log("Connected to client"), setInterval(
() => socket.emit('testEvent', "Message from server sent"),
5000
);
socket.on("disconnect", () => console.log("Client disconnected"));
});
app.get('*', function(req, res) {
res.sendFile(path.join(DIST_DIR, "index.html"));
});
server.listen(PORT, () => console.log("server listening on port " + PORT));
在客户端上,我(我正在使用DataMaps jQuery插件):
import propTypes from 'prop-types';
import React, { Component } from 'react';
import Datamaps from 'datamaps';
import socketIOClient from "socket.io-client";
export default class Datamap extends React.Component {
constructor(props) {
super(props);
this.state = {
response: false,
endpoint: "http://127.0.0.1:3000"
};
window.addEventListener('resize', this.resize);
}
resize() {
if (this.map) {
this.map.resize();
}
}
//creates a new connection to Socket.IO server
componentDidMount() {
const { endpoint } = this.state;
const socket = socketIOClient(endpoint);
socket.on("testEvent", data => this.setState({ response: data }));
this.drawMap();
}
componentWillReceiveProps() {
this.clear();
}
componentDidUpdate() {
this.drawMap();
}
componentWillUnmount() {
this.clear();
window.removeEventListener('resize', this.resize);
}
clear() {
const container = this.refs.container;
for (const child of Array.from(container.childNodes)) {
container.removeChild(child);
}
}
fadingBubbles(layer, data) {
//irrelevant, left out
}
drawMap() {
var map = new Datamaps({
...this.props,
element: this.refs.container,
projection: 'mercator',
responsive: true
});
if (this.props.arc) {
map.arc(this.props.arc, this.props.arcOptions);
}
if (this.props.bubbles) {
map.bubbles(this.props.bubbles, this.props.bubbleOptions);
}
if (this.props.graticule) {
map.graticule();
}
if (this.props.labels) {
map.labels();
}
this.map = map;
this.map.addPlugin('fadingBubbles', this.fadingBubbles.bind(this.map));
}
drawBubbles = () => {
const { response } = this.state;
var data = [
{
"latitude": "28.014067",
"longitude": "-81.728676"
}, {
"latitude": "40.750793",
"longitude": "-73.989525",
"magnitude": 3
}
];
this.map.fadingBubbles(data);
//console.log({ response });
}
render() {
const style = {
position: 'relative',
width: '100%',
height: '100%'
};
return (<div>
<button onClick={this.drawBubbles}>Draw Fading Bubbles</button>
<div ref="container" style={style}></div>
</div>);
}
}
Datamap.propTypes = {
arc: propTypes.array,
arcOptions: propTypes.object,
bubbleOptions: propTypes.object,
bubbles: propTypes.array,
graticule: propTypes.bool,
labels: propTypes.bool
};
所以,目前我有一个按钮。最终函数drawBubbles将从服务器检索lat和long信息并将其提供给地图以显示相应的气泡,但是现在我只想要这些消息,我将能够弄明白。按下按钮时,消息将打印在客户端的控制台上,这是正确的。但是我想摆脱那个按钮,并且能够每5秒钟看到一次消息(所以没有onclick动作),就像在我的服务器中写的那样。我不完全确定组件安装是如何工作的,但是当我只将函数调用this.drawBubbles;
放在render()函数内部的返回之外时,我得到了以下警告(并且没有在控制台上打印): / p>
Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.
Please check the code for the Datamap component.
有人可以解释一下我是如何让这个工作的吗?也许组件在我的应用程序环境中如何工作可能对我有用。
答案 0 :(得分:0)
我怀疑它正在运作,但你不喜欢警告你在卸载时更新状态(我也讨厌它,因为它暗示事情不按预期管理)。我喜欢componentWillUnmount()的这张便条:
在此方法中执行任何必要的清理,例如使计时器无效,取消网络请求或清理在componentDidMount()中创建的任何订阅。
也许考虑在自己的实例中初始化socket.io客户端,生活在Datamap之外,这样就可以将socket.io活动与Datamap组件的生命周期分离。
以下是您可以在Datamap实施中扩展的一个简单示例:
const socket = socketIOClient('http://127.0.0.1:3000');
let listener = null;
socket.on('testEvent', (data) => {
if (listener) {
listener.handleTestEvent({ response: data });
}
});
export class Datamap extends React.Component {
componentWillUnmount() {
listener = null;
}
componentDidMount() {
listener = {
handleTestEvent: (ev) => console.log(ev.response),
};
}
}