You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go服务端接收POST请求时无刷新更新HTML页面的实现方案

实现无刷新更新页面内容的Go服务器方案

问题背景

我正在编写一个支持GET和POST请求的Go服务器,目前GET请求能正常返回HTML页面,POST请求可以接收JSON数据,但只能通过刷新整个页面来更新展示POST接收的数据,希望实现接收POST请求时无需刷新页面就能更新HTML内容。

Go后端修改

需要新增API接口供前端异步获取最新数据,同时优化请求处理逻辑:

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // 处理POST请求
    if r.Method == "POST" {
        b, err := io.ReadAll(r.Body)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        event := r.URL.Query().Get("event")
        switch event {
        case "up":
            err = h.up(b)
        case "join":
            err = h.join(b)
        default:
            fmt.Printf("事件%s对应的处理器未实现 \n", event)
            http.Error(w, "未实现的事件类型", http.StatusBadRequest)
            return
        }
        if err != nil {
            fmt.Printf("请求方法'%s'返回错误:%s\n", event, err)
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        // POST请求处理完成后返回成功响应
        w.WriteHeader(http.StatusOK)
        return
    }

    // 处理GET请求
    switch r.URL.Path {
    case "/":
        // 加载并渲染网页模板
        tmpl := template.Must(template.ParseFiles("layout.html"))
        tmpl.Execute(w, data)
    case "/api/devices":
        // 新增API接口,返回最新的设备数据JSON
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(data.Dispositivos)
    default:
        http.NotFound(w, r)
        return
    }
}

修改说明

  • 拆分POST与GET请求处理逻辑,结构更清晰
  • 新增/api/devices接口,专门返回设备数据的JSON格式,供前端异步获取
  • 完善错误处理,返回标准HTTP状态码,避免直接panic

前端HTML修改

修改<script>部分,通过异步请求获取最新数据并动态更新页面:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="author" content="Jorge Felipe González Orellana"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            *{
                box-sizing: border-box;
                padding: 0;
                margin: 0;
            }

            body {
                background-color: #7A82AB;
                color: floralwhite;
                font-family: Arial, Helvetica, sans-serif;
                margin: 0;
            }

            .nav-grnl {
                display: flex;
                align-items: center;
                justify-content: center;
                background-color: #333333;
                height: 7vh;
            }

            .nav-grnl a {
                margin: 10px 10px 10px 10px;
                padding: 8px 16px;
                display: flex;
                text-decoration: none;
                color: floralwhite;
                border-radius: 12px;
            }

            .nav-grnl a:hover {
                color: black;
                background-color: floralwhite;
            }

            .logo {
                display: flex;
                position: fixed;
                left: 0;
                height: inherit;
                width: 7vh;
            }

            .contenedor-gnrl {
                display: grid;
                position: fixed;
                grid-template-areas: 
                    'left right';
                width: 100vw;
                height: 88vh;
            }

            .main-section {
                background-color: floralwhite;
                color: black;
                grid-area: left;
                width: 80vw;
            }

            .main-info {
                background-color: #999792;
                color: black;
                grid-area: right;
                width: 20vw;
            }

            .footer-gnrl {
                background-color: #333333;
                display: flex;
                align-items: center;
                justify-content: center;
                position: fixed;
                bottom: 0;
                width: 100vw;
                height: 5vh;
            }

            p {
                margin: 0;
                border: 0;
                padding: 0;
            }

            @media (max-width: 600px) {
                .grid-container  {
                    grid-template-areas: 
                    'header header' 
                    'left left' 
                    'right right' 
                    'footer footer';
                }
            }
        </style>
        <title>2veinte test</title> 

        <script>
            // 定时获取最新设备数据并更新页面
            setInterval(updateDevices, 1000);

            function updateDevices() {
                fetch('/api/devices')
                    .then(response => response.json())
                    .then(devices => {
                        const container = document.getElementById('DispositivosLoraWAN');
                        // 清空现有内容
                        container.innerHTML = '';
                        // 遍历设备数据生成新DOM元素
                        devices.forEach(device => {
                            const deviceDiv = document.createElement('div');
                            deviceDiv.innerHTML = `
                                <h6>${device.Nombre_Disp}</h6>
                                <h6>${device.DevEUI}</h6>
                                <h6>${device.Data}</h6>
                            `;
                            container.appendChild(deviceDiv);
                        });
                    })
                    .catch(error => console.error('获取设备数据失败:', error));
            }
        </script>      
    </head>
    <body>       
        <div class="nav-grnl">
            <svg class="logo"></svg>
            <a href="/">Link</a>
            <a href="/">Link</a>
            <a href="/">Link</a>
        </div>

        <div class="contenedor-gnrl">
            <div class="main-section">
                <div class="DispositivosLoraWAN" id="DispositivosLoraWAN">
                    <!-- 内容由JS动态生成 -->
                </div>
            </div>

            <div class="main-info">
                <p>主信息</p>
            </div>
        </div>

        <div class="footer-gnrl">
            <p>页脚</p>
        </div>
    </body>
</html>

修改说明

  • 使用fetch API异步请求后端/api/devices接口获取最新数据
  • 每次获取数据后,清空容器并重新生成DOM元素,实现无刷新更新
  • 移除模板中的静态循环渲染,改为JS动态生成内容

内容的提问来源于stack exchange,提问作者Jorge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:54:54