我使用以下服务器代码从postgres数据库检索数据:
const express = require('express')
const app = express()
const server = require('http').createServer(app);
const pool = require("postgresql");
const WebSocket = require('ws');
const wss = new WebSocket.Server({ server:server });
const getTempData = async () => {
try {
const tempData = await pool.query("select country, temp from my_temp_table");
return JSON.stringify(tempData.rows)
} catch(err) {
console.error(err.messasge);
}
}
wss.on('connection', async (webSocketClient) => {
console.log('A new client Connected!');
const tempDetails = await getTempData();
webSocketClient.send(tempDetails);
webSocketClient.on('message', (message) => {
console.log('received: %s', message);
});
});
server.listen(3000, () => console.log(`Listening on port :3000`))
现在,在客户端,我已经创建了以下到localhost 3000的websocket连接。
当第一次呈现下面的客户端代码时,数据显示我也获得所有控制台日志消息,即ws opened
,getting data....
,最后控制台记录实际的data
。
isPaused
也设置为false。
我面临的问题和不确定问题是什么,是我希望看到我的客户端页面更新国家/临时数据(没有页面刷新),当我更新my_temp_table
数据库表中的国家/临时值时,但它没有。
我期望的结果是,通过websocket,任何时候我在服务器端的表更新,客户端将更新tempData
,通过下面的第二个useEffect钩子。
我基本上希望客户端拉入并通过websocket显示服务器的更改,当后端数据库表中的数据发生变化时。
import React, { useState, useEffect, useRef } from 'react';
export default function Temperature() {
const [isPaused, setPause] = useState(false);
const [tempData, setTempData] = useState([]);
const [name, setName] = useState(null);
const ws = useRef(null);
useEffect(() => {
ws.current = new WebSocket("ws://localhost:3000");
ws.current.onopen = () => {
console.log("ws opened");
}
ws.current.onclose = () => console.log("ws closed");
return () => {
ws.current.close();
};
}, []);
useEffect(() => {
if (!ws.current) return;
ws.current.onmessage = e => {
if (isPaused) return;
console.log("getting temp data....");
const data = JSON.parse(e.data);
setTempData(data)
console.log("data: ",data);
};
}, [isPaused]);
return (
<div>
<button onClick={() => setPause(!isPaused)}>
{isPaused ? "Resume" : "Pause"}
</button>
{ tempData?
tempData.map((data, i) => (
<div>
<span>{data.country}</span>
<span>{data.temp}</span>
</div>
))
: null }
</div>
)
}
代码只执行一次,因为没有对web套接字send
事件的递归调用。当创建web套接字时,它从数据库中获取数据并发送数据,这就是它。
您可能需要某种动作来多次触发此事件。例如,在您的代码中:
wss.on("connection", async webSocketClient => {
console.log("A new client Connected!");
setInterval(() => {
const timeNow = Date.now();
webSocketClient.send(
JSON.stringify([
{ country: "country-a", temp: timeNow },
{ country: "country-b", temp: timeNow },
])
);
}, 1000);
webSocketClient.on("message", message => {
console.log("received: %s", message);
});
});
我看到你正在使用一些包池从PostgreSQL数据库。看一下另一个例子。
您的客户端如何知道服务器端数据库是否有任何变化?您可以创建一个在每次特定数据更改时触发的事件,并在客户端套接字上侦听这些事件。就像你在当前代码中处理onmessage事件一样。
你可以根据这个事件来呈现react组件。