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

Express+Puppeteer项目提交表单后结果页需刷新显示数据,如何等POST处理完成再加载?

问题根因分析

你现在遇到的问题核心是异步逻辑没有等待就提前返回,具体有3个核心错误:

  • 服务端App函数是包含Puppeteer爬取、OCR识别的长耗时异步逻辑,你在POST接口里直接调用App()没有加await,接口收到请求后立刻结束响应,前端无法得知处理进度,提前跳转自然拿不到还没生成的数据。
  • 全局textArray设计完全不合理,多用户同时访问时所有用户的结果会混杂在一起,严重影响数据正确性。
  • GET /results接口中你连续调用了res.sendFile和res.send,响应在调用sendFile后就已经关闭,后续的数组数据根本不会发出去。
服务端修改方案
  1. 首先修改App函数,让它返回异步处理的最终结果,把内部的main()调用改为返回Promise,同时调整getImageText方法将识别到的文本返回,删掉全局textArray:
// 改造App函数返回Promise和结果
const App = async (pinNum, dateOfB) => {
  // ... 原有配置代码全部保留
  async function main() {
    // ... 原有爬取代码全部保留
    const text = await getImageText(); // 拿到识别结果
    await page.close();
    await browser.close();
    await deleteImage();
    return text; // 返回最终识别结果
  }
  return main(); // 返回main的Promise,供外部await
}

// 改造getImageText返回识别文本
async function getImageText() {
  // ... 原有OCR逻辑全部保留
  const text = annotation ? annotation.description : "";
  // ... 原有FCM推送逻辑全部保留
  return text; // 新增返回识别结果
}
  1. 改造POST /results接口,等待异步处理完成后直接返回结果:
app.use(express.json()); // 新增:支持解析JSON格式的请求体
app.post("/results", async (req, res) => {
  try {
    const pin = req.body.pin;
    const dateOfBirth = req.body.dateOfBirth;
    const result = await App(pin, dateOfBirth);
    res.json({ success: true, data: result });
  } catch (err) {
    console.error(err);
    res.status(500).json({ success: false, msg: "处理失败,请检查PIN和出生日期后重试" });
  }
});
  1. 简化GET /results接口,只返回静态页面:
app.get("/results", (req, res) => {
  res.sendFile(__dirname + "/src/results.html");
});
客户端React修改方案
  1. 表单提交禁用原生默认跳转行为,改为异步提交,添加加载状态提示,等接口返回结果后再携带数据跳转到结果页:
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';

function LoginPage() {
  const [pin, setPin] = useState('');
  const [dob, setDob] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');
  const navigate = useNavigate();

  const handleSubmit = async (e) => {
    e.preventDefault(); // 阻止原生表单默认提交跳转
    setLoading(true);
    setError('');
    try {
      const res = await axios.post('/results', { pin, dateOfBirth: dob });
      // 拿到结果后跳转到结果页,携带数据
      navigate('/results', { state: { resultText: res.data.data } });
    } catch (err) {
      setError(err.response?.data?.msg || '提交失败,请稍后重试');
    } finally {
      setLoading(false);
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input value={pin} onChange={e => setPin(e.target.value)} placeholder="请输入PIN码" required />
      <input value={dob} onChange={e => setDob(e.target.value)} placeholder="请输入出生日期" required />
      <button type="submit" disabled={loading}>{loading ? '处理中,请稍候...' : '提交'}</button>
      {error && <p style={{color: 'red'}}>{error}</p>}
    </form>
  )
}
  1. 结果页直接读取路由传递的参数展示即可,无需刷新:
import { useLocation, Navigate } from 'react-router-dom';

function ResultsPage() {
  const location = useLocation();
  const resultText = location.state?.resultText;
  
  // 没有数据时跳回登录页
  if (!resultText) return <Navigate to="/" replace />;
  
  return (
    <div>
      <h1>识别结果</h1>
      <pre>{resultText}</pre>
    </div>
  )
}

修改完成后即可实现提交后等待处理完成再跳转结果页,无需手动刷新就能拿到数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:24:03