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

Node.js点击登录按钮提交后无法跳转加载新HTML页面问题

问题原因

你现在用fetch发异步POST请求,哪怕服务端把cardcast.html的内容返回了,这些内容只会存在fetch的响应对象里,浏览器不会自动替换当前页面,自然看不到跳转效果。另外代码里还有几个隐性问题:

  • 响应没设置正确的Content-Type头,浏览器无法正确识别返回内容类型
  • new_player没有变量声明,会变成污染全局的隐式变量
  • 用相对路径读前端文件,很容易因为服务端启动目录不对找不到文件
  • JSON.parse是同步方法,不需要加await
修复方案

1. 调整服务端代码

先引入path模块处理文件路径,补全路由逻辑、响应头,修正语法问题,改完的完整代码如下:

const http = require('http');
const fs = require('fs');
const path = require('path');

console.log('running');

let player_count = 0;
let players = [];

class player
{
    constructor(id)
    {
        this.id = id;
        this.name = "";
        this.card_czar = false;
        this.cards = new Set();
        this.score = 0;
        this.selection = "";
    }

    setName(nick_name)
    {
        this.name = nick_name;
    }

    setCardCzar(czar_boolean)
    {
        this.card_czar = czar_boolean;
    }

    delCard(card_val)
    {
        this.cards.delete(card_val);
    }

    addCard(card_val)
    {
        this.cards.add(card_val);
    }

    addScore()
    {
        this.score++;
    }
}

// 固定前端文件夹的绝对路径,避免相对路径出错
const FRONTEND_PATH = path.resolve(__dirname, '../frontend');

let server = http.createServer(async (req, res) => {
    console.log(req.url);

    if (req.url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        res.write(fs.readFileSync(path.join(FRONTEND_PATH, 'test.html')));
        res.end();
    }
    else if (req.url === '/login' && req.method === 'POST') {
        const buffers = [];
        for await (const chunk of req) {
            buffers.push(chunk);
        }
        const data = JSON.parse(Buffer.concat(buffers).toString());

        let new_player = new player(player_count);
        new_player.setName(data.nickname);
        players.push(new_player);
        player_count++;
        console.log(players);

        // 登录成功返回200状态即可
        res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
        res.end(JSON.stringify({ code: 0, msg: '登录成功' }));
    }
    // 新增游戏页面路由
    else if (req.url === '/game') {
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        res.write(fs.readFileSync(path.join(FRONTEND_PATH, 'cardcast.html')));
        res.end();
    }
    else {
        res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
        res.end('页面不存在');
    }
});

server.listen(3000);

2. 调整前端登录逻辑

修改登录页的login函数,在fetch请求提交昵称成功后,手动跳转到游戏页路由即可,同时修正之前拼接请求URL的问题(直接写绝对路径/login比拼接window.location.href稳妥,避免带参数时路径错误):

<script type="text/javascript">  
    async function login()
    {
        let nickname = document.getElementById('username-field').value.trim();
        if (!nickname) {
            alert('请输入昵称');
            return;
        }
        console.log(nickname);

        // 提交昵称到登录接口
        await fetch('/login', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({nickname})
        });
        // 提交成功后跳转到游戏页
        window.location.href = '/game';
    }
</script>

如果你不想单独加/game路由,也可以在fetch拿到/login返回的HTML内容后直接替换当前页面,不过这种方式后续加载游戏页的CSS、JS等静态资源容易出路径问题,不推荐使用,写法参考:

let res = await fetch('/login', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({nickname})
});
let html = await res.text();
document.open();
document.write(html);
document.close();
额外提醒
  • 目前用fs.readFileSync读文件是同步阻塞操作,小范围测试没问题,并发高了会阻塞服务进程,后续可以换成fs/promises模块的异步读文件方法
  • 后续cardcast.html如果引用了独立的CSS、JS、图片等资源,记得在服务端加对应的静态资源处理逻辑,不然这些资源会加载失败
  • 现在玩家数据全存在服务端内存里,服务端重启后所有数据都会清空,需要长期保存的话可以后续接入文件存储或者数据库

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:48:11