JS fetch连续两次调用response.json()为何后续.then不执行
Fetch请求中连续调用response.json()导致后续.then不执行的原因
核心原理
Response对象的请求体(body)是只读的单向ReadableStream(可读流),流的读取操作是一次性的:一旦被某个读取方法消费,就会被锁定,无法再次读取。response.json()、response.text()、response.blob()、response.formData()这类方法的本质,都是消费body流、将原始二进制数据解析为对应格式的内容,返回一个Promise。同一个Response对象上,这类方法只能成功调用一次。
代码问题分析
- 异常代码的问题:在第一个.then里连续调用了两次
response.json()- 第一次执行
console.log(response.json())时,已经触发了流的读取,body流被第一次调用消费、锁定 - 第二次执行
return response.json()时,流已经被读取完毕,方法会直接返回一个rejected状态的Promise,抛出「Body has already been read」类型的错误,Promise链直接进入异常分支,由于没有写.catch()捕获错误,所以看不到控制台报错,后续的.then自然不会执行
- 第一次执行
- 正常运行的代码逻辑:只调用了一次
response.json(),把返回的Promise存在变量resp中,后续打印、返回操作都是复用同一个Promise实例,没有重复消费body流,所以流程能正常走到第二个.then,拿到解析后的JSON数据。
正确写法参考
const fetchPromise = fetch('https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json'); console.log(fetchPromise) fetchPromise .then( response => { const resp = response.json(); // 仅调用一次读取方法,拿到解析Promise console.log(resp); return resp; }) .then( json => { console.log(json[0].name); // 正常输出: baked beans }) .catch(err => { // 建议始终添加catch捕获请求、解析阶段的异常 console.error('请求处理异常:', err); });
注意:所有读取Response body的方法都遵循「只能调用一次」的规则,不要在同一个Response上重复调用这类读取方法,也不要同时调用多个不同的body读取方法(比如先调用json()再调用text()),否则都会触发流读取错误。
内容的提问来源于stack exchange,提问作者Hasnain Ali
相关产品推荐
相关产品推荐

