使用JavaScript的fetch发送Partial/Ajax请求仅获部分响应的问题
问题描述
我用JavaScript的fetch发起POST请求,目标服务器返回XML格式的partial-response,但响应是分块返回的,fetch只能拿到第一部分内容。试过await、then等异步处理方式,结果还是一样。
我的请求代码:
let response = await fetch(url, { method: 'POST', body: // 请求体内容 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Connection': 'close', 'Faces-Request': 'partial/ajax', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/xml, text/xml, */*; q=0.01', 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', // 其他Cookie、User-Agent等头信息 }});
尝试过XMLHttpRequest,但误以为需要手动设置Cookie头(受浏览器安全限制无法直接设置),所以没成功使用。
期望的完整响应:
<?xml version='1.0' encoding='UTF-8'?> <partial-response id="j_id1"> <changes> <update id="form:messages"> <![CDATA[_]]></update> <update id="form:j_idt117"> <![CDATA[_]]></update> <update id="form:j_idt133"> <![CDATA[_]]></update> <update id="form:j_idt228"> <![CDATA[_]]></update> <update id="j_id1:javax.faces.ViewState:0"><![CDATA[_]]></update> </changes> </partial-response>
实际获取到的响应:
<?xml version='1.0' encoding='UTF-8'?> <partial-response id="j_id1"> <changes> <update id="form:j_idt228"> <![CDATA[_]]></update> <update id="j_id1:javax.faces.ViewState:0"><![CDATA[_]]></update> </changes> </partial-response>
想知道fetch有没有机制能获取完整的分块响应,曾考虑等待响应完全返回后再读取,但没找到相关文档。
解决方案
1. 移除Connection: close头
你设置的Connection: close会强制服务器发送部分数据后关闭连接,导致fetch无法接收后续分块内容。浏览器默认使用keep-alive连接,移除这个头即可让服务器完整发送所有分块:
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', // 移除 'Connection': 'close' 'Faces-Request': 'partial/ajax', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/xml, text/xml, */*; q=0.01', // 重复的Accept头会被浏览器忽略,保留一个合适的即可 'Accept-Encoding': 'gzip, deflate', // 其他Cookie、User-Agent等头信息 }
2. 正确读取完整响应体
fetch会自动等待所有分块接收完成后返回response对象,你需要通过response.text()或response.xml()(部分浏览器支持)读取完整内容:
let response = await fetch(url, { /* 调整后的配置 */ }); // 读取完整响应文本 let fullXmlText = await response.text(); // 解析为XML文档 let parser = new DOMParser(); let xmlDoc = parser.parseFromString(fullXmlText, "application/xml"); // 后续操作xmlDoc即可获取完整的partial-response
3. 关于XMLHttpRequest的Cookie问题
XMLHttpRequest不需要手动设置Cookie头,浏览器会自动携带当前域名下的Cookie(同源请求默认支持)。如果是跨域请求,只需开启withCredentials即可:
let xhr = new XMLHttpRequest(); xhr.open('POST', url); xhr.withCredentials = true; // 跨域时允许携带Cookie xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); xhr.setRequestHeader('Faces-Request', 'partial/ajax'); // 其他必要头设置 xhr.onload = function() { if (xhr.status === 200) { let xmlDoc = xhr.responseXML; // 处理完整响应内容 } }; xhr.send(body);
4. 验证服务器传输编码
检查服务器响应头是否包含Transfer-Encoding: chunked,如果是,只要连接保持打开(移除Connection: close),fetch会自动拼接所有分块内容。
内容的提问来源于stack exchange,提问作者Nicolas B.
相关产品推荐
相关产品推荐

