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

IT技术 javascript node.js reactjs express websocket
2021-04-28 01:52:28

我正在使用以下服务器代码从 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 openedgetting 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>
  )
}
2个回答

代码只执行一次,因为没有对 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 组件。