首页 > 解决方案 > 客户端通过 websocket 连接从后端服务器数据库表中检索数据

问题描述

我正在使用以下服务器代码从 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也设置为假。

我面临的问题并且不确定问题是什么,当我更新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>
  )
}

标签: javascriptnode.jsreactjsexpresswebsocket

解决方案


该代码只执行一次,因为没有对 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 数据库中汇集。看看这个其他例子


推荐阅读