如何让Fetch API的Promise尽快resolve?
如何让Fetch API的Promise尽快resolve?
这个问题我之前也踩过坑!Fetch API的Promise确实要等到响应头完全接收,且浏览器确认可以开始处理响应体时才会resolve,而你碰到的8秒延迟,大概率是被Express的响应缓冲机制卡住了——哪怕你调用了res.write(),Express默认会攒够一定量的数据才会真正发送给客户端,导致客户端迟迟收不到第一个数据块,Fetch的Promise就一直pending。
问题根源
Express默认开启了响应缓冲:它会把你通过res.write()写入的数据暂存在内存里,直到缓冲达到阈值(通常是几KB)或者你调用res.end()才会一次性发送给客户端。而XHR的progress事件只要有任何数据(哪怕是小 chunk)到达就会触发,所以它能快速响应,但Fetch的Promise必须等到第一个有效数据块被浏览器接收到才会resolve。
解决方案:强制关闭缓冲,立刻发送数据
你只需要修改服务器代码,提前发送响应头并强制刷新缓冲,让第一个数据块尽快到达客户端:
修改后的服务器代码
app.post("/bulk-update", (req, res) => { // 1. 明确设置分块传输,禁用代理层缓冲(若用Nginx等反向代理) res.setHeader('Transfer-Encoding', 'chunked'); res.setHeader('X-Accel-Buffering', 'no'); // 2. 立刻发送响应头,让客户端先收到头信息 res.flushHeaders(); buildTask(req.body, 5, (status) => { const completed = status.success + status.error; const remaining = status.total - completed; if (remaining === 0) { res.write(`${JSON.stringify(status)}\n`); res.flush(); // 3. 强制发送当前缓冲的内容,不等缓冲满 res.end(); return; } if (completed % 10 === 0) { res.write(`${JSON.stringify(status)}\n`); res.flush(); // 每次写入后都强制刷新,确保数据即时发送 } }); });
关键改动说明
res.flushHeaders():立刻把响应头发送给客户端,而不是等到缓冲满。这一步能让浏览器先确认响应的基本信息(状态码、头信息),为后续接收响应体做好准备。res.flush():每次调用res.write()后,强制把当前内存中的数据发送给客户端,绕过Express的缓冲阈值限制,确保第一个状态更新能快速到达浏览器。X-Accel-Buffering: no:如果你的Express服务部署在Nginx等反向代理后面,这个头会告诉代理不要缓冲响应数据,避免代理层再次卡住数据。
测试验证
修改后,Fetch的Promise应该会在50ms内resolve(和你XHR的progress事件触发时间差不多),因为浏览器一旦收到响应头和第一个数据块,就会立刻resolve Fetch的Promise,你就能开始处理响应体了。
备注:内容来源于stack exchange,提问作者Wio
相关产品推荐
相关产品推荐

