Express+Puppeteer项目提交表单后结果页需刷新显示数据,如何等POST处理完成再加载?
问题根因分析
你现在遇到的问题核心是异步逻辑没有等待就提前返回,具体有3个核心错误:
- 服务端
App函数是包含Puppeteer爬取、OCR识别的长耗时异步逻辑,你在POST接口里直接调用App()没有加await,接口收到请求后立刻结束响应,前端无法得知处理进度,提前跳转自然拿不到还没生成的数据。 - 全局
textArray设计完全不合理,多用户同时访问时所有用户的结果会混杂在一起,严重影响数据正确性。 GET /results接口中你连续调用了res.sendFile和res.send,响应在调用sendFile后就已经关闭,后续的数组数据根本不会发出去。
服务端修改方案
- 首先修改
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; // 新增返回识别结果 }
- 改造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和出生日期后重试" }); } });
- 简化GET /results接口,只返回静态页面:
app.get("/results", (req, res) => { res.sendFile(__dirname + "/src/results.html"); });
客户端React修改方案
- 表单提交禁用原生默认跳转行为,改为异步提交,添加加载状态提示,等接口返回结果后再携带数据跳转到结果页:
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> ) }
- 结果页直接读取路由传递的参数展示即可,无需刷新:
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
相关产品推荐
相关产品推荐

