
expo 应用在连续点击 5 次后无响应却无报错,问题实际源于后端未正确结束 http 响应(res.end() 缺失),导致客户端 fetch 请求挂起、连接池耗尽,最终 ui 冻结。
expo 应用在连续点击 5 次后无响应却无报错,问题实际源于后端未正确结束 http 响应(res.end() 缺失),导致客户端 fetch 请求挂起、连接池耗尽,最终 ui 冻结。
该问题表面表现为 React Native 前端“假死”——点击失效、界面无反馈、控制台无错误日志,极易误判为 React 渲染逻辑或状态管理缺陷。但根本原因在于 Node.js 后端处理 POST 请求时遗漏了响应终结调用:
// ❌ 错误示例:缺少 res.end() 或 res.send()
app.post('/like', (req, res) => {
const { frage, like, datum } = req.body;
createLike({ frage, like, datum });
// ⚠️ 此处未发送响应!请求将永远挂起
});
当 fetch 发起请求后,若服务端未调用 res.end()、res.send() 或 res.json(),HTTP 连接不会关闭。现代浏览器和 React Native 的 fetch 实现默认限制同源并发连接数(通常为 6 个)。前 5 次点击触发 5 个未完成请求,第 6 次点击时因连接池占满而阻塞,UI 看似“冻结”,实则是后续交互被网络层阻塞。
✅ 正确写法必须显式结束响应:
app.post('/like', async (req, res) => {
try {
const { frage, like, datum } = req.body;
await createLike({ frage, like, datum });
res.status(200).json({ success: true, message: 'Saved' }); // ✅ 显式响应
} catch (error) {
console.error('Save failed:', error);
res.status(500).json({ error: 'Server error' }); // ✅ 错误路径也需响应
}
});
此外,前端代码存在可优化点以增强健壮性:
- useEffect 中的 fetch 调用未做防重复提交控制,建议添加加载状态或节流;
- setClick 更新逻辑中误用了 prev 参数(实际未使用),应改为函数式更新确保基于最新状态;
- setTimeout 清理逻辑正确,但 thankyou 状态重置可合并至同一 effect,避免冗余 timer。
总结:此类“无错误冻结”问题,90% 源于后端响应未终结。排查时应优先检查网络面板(Chrome DevTools 或 React Native Debugger)中是否有 pending 请求;后端务必保证每个路由处理分支都调用 res.send()/res.json()/res.end();前端可增加 fetch 超时与 AbortController 防止长期阻塞。











