客户端通过 websocket 连接从后端服务器数据库 table 检索数据

Client to retrieve data from backend server database table via a websocket connection

我正在使用以下服务器代码从 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`))

现在在客户端,我创建了以下到本地主机 3000 的 websocket 连接。

当第一次呈现下面的客户端代码时,数据显示在那里我也得到了所有的控制台日志消息,即 ws openedgetting data.... 和最后的控制台记录实际的 data

isPaused 也设置为 false。

我面临的问题是我不确定问题是什么,当我更新 country/temp 时,我希望看到我的客户端页面更新 country/temp 数据(没有页面刷新) my_temp_table 数据库 table 中的值,但它没有。

我预期的结果是,通过 websocket,只要我在服务器端更新 table,客户端就会通过下面的第二个 useEffect 挂钩更新 tempData

我基本上希望当后端数据库中的数据发生变化时,客户端通过 websocket 拉入并显示来自服务器的变化 table。

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>
  )
}

您的客户如何知道服务器端的数据库是否有任何变化? 您可以创建一个事件,每次特定数据更改时都会触发该事件,并在您的客户端套接字上侦听这些事件。就像您在当前代码中处理 onmessage 事件一样。

你可以根据这个事件渲染react组件

代码只执行一次,因为没有重复调用网络套接字 send 事件。创建网络套接字后,它会从数据库中获取数据并发送,仅此而已。

您可能需要某种多次触发此事件的操作。例如,在您的代码中:

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 数据库中进行池化。看看this other example.