Javascript 在HTTP错误422的情况下,如何使用fetch获取响应正文?
我在后端有一个API,它在调用成功的情况下发送状态Javascript 在HTTP错误422的情况下,如何使用fetch获取响应正文?,javascript,reactjs,http,error-handling,fetch,Javascript,Reactjs,Http,Error Handling,Fetch,我在后端有一个API,它在调用成功的情况下发送状态201,如果 提交数据中的任何错误都会发送状态422(不可处理实体),json响应如下: { "error": "Some error text here explaining the error" } 此外,它还发送404,以防API由于某种原因无法在后端工作 在前端,我使用以下代码获取响应,并根据响应状态代码执行成功或错误回调: fetch(“api\u url\u此处”{ 方法:“这里的一些方
201
,如果
提交数据中的任何错误都会发送状态422
(不可处理实体),json响应如下:
{
"error": "Some error text here explaining the error"
}
此外,它还发送404
,以防API由于某种原因无法在后端工作
在前端,我使用以下代码获取响应,并根据响应状态代码执行成功或错误回调:
fetch(“api\u url\u此处”{
方法:“这里的一些方法”,
凭据:“相同来源”,
标题:{
“内容类型”:“应用程序/json;字符集=UTF-8”,
“X-CSRF-Token”:“这里有一些Token”
}
})
.然后(检查状态)
.then(函数json(响应){
返回response.json()
})
.然后(功能(resp){
成功回调(resp)
})
.catch(函数(错误){
errorCallback(错误);
});
//上面使用的状态函数
检查状态=(响应)=>{
如果(response.status>=200&&response.status<300){
返回承诺。解决(响应)
}否则{
返回承诺。拒绝(新错误(响应))
}
}
简短回答
因为您假设您两次解析响应内容是不正确的。在原始代码段中,当满足错误条件时,将跳过then(checkStatus)
之后的then
长答案
一般来说,结构良好的项目包括:
然后
仅在履行承诺时运行的处理程序catch
仅在拒绝承诺时运行的处理程序最终
(可选)在承诺结算时运行(在2或3中)fetch
方法,因此不管响应的状态如何,都会调用第一个then
方法。在您的第一个处理程序中,回调将返回已履行或已拒绝的承诺
如果实现,它将控制权传递给链中的下一个然后方法调用,您可以通过调用响应上的JSON
方法来提取JSON,然后将该方法作为承诺值传递给最后一个然后方法以在成功回调中使用
如果被拒绝,控件将传递给catch
方法调用,该方法调用将接收值设置为newerror(response)
的承诺,然后立即传递给errorCallback
。因此,后者接收Error
的实例,其值是from Fetch API的实例
这正是您在日志中看到的:Error:[object Response]
,这是对Error
实例调用toString
方法的结果。第一部分是构造函数名称,第二部分是内容的字符串标记(形式为[type constructor])
怎么办?
由于您的API为每个可能的用例返回JSON响应(201
、404
、422
),因此将解析后的响应传递给已履行和已拒绝的承诺。另外,请注意,您在全局作用域上意外声明了checkStatus
,忽略了var
、const
或let
关键字:
//模拟响应对象
常数res={
现状:200,
身体:“模仿”,
异步json(){
常数{
身体
}=这个;
返回体;
}
};
const checkStatus=异步(响应)=>{
const parsed=wait response.json();
常数{
地位
}=响应;
如果(状态>=200&&status<300){
返回解析;
}
return Promise.reject(新错误(已解析));
};
常数测试=()=>{
返回检查状态(res)
.then(console.log)
.catch((错误)=>console.warn(错误消息))
.最后(()=>{
如果(资源状态===200){
res.status=422;
返回测试();
}
});
};
test()代码>这是因为在发生错误的情况下,将跳过处理程序并执行catch处理程序,checkStatus
返回拒绝的承诺,然后绕过剩余的链
这就是我重构代码的方法
checkStatus = async (response) => {
if (response.status >= 200 && response.status < 300)
return await response.json()
throw await response.json()
}
}
fetch("api_url_here", {
method: 'some_method_here',
credentials: "same-origin",
headers: {
"Content-type": "application/json; charset=UTF-8",
'X-CSRF-Token': "some_token_here"
}
})
.then(checkStatus)
.then(successCallback)
.catch(errorCallback);
checkStatus=async(响应)=>{
如果(response.status>=200&&response.status<300)
return wait response.json()
抛出wait response.json()
}
}
获取(“api\u url\u此处”{
方法:“这里的一些方法”,
凭据:“相同来源”,
标题:{
“内容类型”:“应用程序/json;字符集=UTF-8”,
“X-CSRF-Token”:“这里有一些Token”
}
})
.然后(检查状态)
。然后(成功回调)
.catch(错误回调);
另外,通过使用async/await
Response,可以更好地直观地查看此代码。json()是异步的,因此您可能希望使checkStatus异步并等待response@SørenEriksen是的,我理解这一点,但在checkStatus中获取响应可能不是最干净的方式。我这样做只是为了检查之前发生的事情。在您定义的checkStatus函数中,您编写了const parsed=response.json()代码>。在执行此语句之前是否需要一个wait
,在checkStatus函数本身之前是否需要一个async
。否则,IF语句中的返回Promise.resolve(已解析)
将在解析response.json()
之前运行。我是否错过了它?哦,当然,它必须与等待,我的坏。教训是-永远不要将原始代码段用作框架:)我甚至在主要代码段中提到了“json方法返回承诺!”。此外,我代码段中的这段代码导致了问题return Promise.reject(新错误(已解析))代码>。。。。将解析后的响应包装在新错误中
导致它丢失json消息