gpt4 book ai didi

javascript - 如果出现 HTTP 错误 422,如何使用 fetch 获取响应正文?

转载 作者:行者123 更新时间:2023-12-01 14:50:16 46 4
gpt4 key购买 nike

我在后端有一个发送状态的 API 201如果通话成功并且有
提交的数据有任何错误,它会发送状态 422 (无法处理的实体)具有如下 json 响应:

{
"error": "Some error text here explaining the error"
}
此外,它还会发送 404以防 API 由于某种原因无法在后端工作。
在前端,我使用以下代码来获取响应并根据响应状态代码执行成功或错误回调:

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(function json(response) {
return response.json()
})
.then(function(resp){
successCallback(resp)
})
.catch(function(error){
errorCallback(error);
});

//status function used above
checkStatus = (response) => {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response))
}
}
successCallback在状态码 201 的情况下,函数能够以正确的 JSON 格式接收响应但是当我尝试在 errorCallback 中获取错误响应时( status: 422 )它显示如下内容(在控制台中记录响应):
Error: [object Response]
at status (grocery-market.js:447)
当我尝试 console.log将其包装在 new Error() 中之前的错误响应像这样,
  checkStatus = (response) => {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
console.log(response.json()) //logging the response beforehand
return Promise.reject(new Error(response.statusText))
}
}
我在控制台中得到以下 promise ( [[PromiseValue]] 属性实际上包含我需要的错误文本)
enter image description here
有人可以解释为什么这只会在错误情况下发生,即使我正在调用 response.json()在错误和成功的情况下?
我怎样才能以干净的方式解决这个问题?
编辑:
我发现如果我创建另一个 json()对错误响应的 promise 我能够得到正确的错误:

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(function json(response) {
return response.json()
})
.then(function(resp){
successCallback(resp)
})
.catch(function(error){
error.json().then((error) => { //changed here
errorCallback(error)
});
});

但是为什么我要调用另一个 .json()在错误情况下的响应?

最佳答案

简答
因为您对两次解析响应内容的假设是不正确的。在原始片段中,thenthen(checkStatus) 之后满足错误条件时跳过。
长答案
一般来说,结构良好promise chain包括:

  • promise 在 future 某个时间实现或拒绝
  • then仅在实现 Promise
  • 时运行的处理程序
  • catch仅在拒绝 Promise
  • 时运行的处理程序
  • finally (可选)在 Promise 结算时运行(在 2 或 3 中)

  • 2 和 3 中的每个处理程序都返回一个 Promise 以启用链接。
    接下来, fetch Fetch API 的方法 rejects only on network failures ,所以第一个 then不管 status响应的代码。您的第一个处理程序, onFulfilled 回调返回一个已完成或被拒绝的 Promise。
    如果满足,它将控制权交给下一个 then链中的方法调用,通过调用 json 提取 JSON响应上的方法,然后将其作为 Promise 值传递给最后一个 then successCallback 中使用的方法.
    如果被拒绝,控制权将传递给 catch方法调用,它接收值设置为 new Error(response) 的 Promise然后您立即传递给 errorCallback .因此,后者接收到 Error 的实例。 ,其值为 Response 的实例从获取 API。
    这正是您所看到的记录: Error: [object Response] ,调用 toString 的结果 Error 实例上的方法.第一部分是构造函数名称,第二部分是内容的字符串标记(形式为 [type Constructor])。
    该怎么办?
    由于您的 API 针对每个可能的用例( 201404422 )返回 JSON 响应,请将解析后的响应传递给已完成和已拒绝的 promise 。另外,请注意您不小心声明了 checkStatus通过省略 var 在全局范围内, const , 或 let关键词:

    //mock Response object
    const res = {
    status: 200,
    body: "mock",
    async json() {
    const {
    body
    } = this;
    return body;
    }
    };

    const checkStatus = async (response) => {

    const parsed = await response.json();

    const {
    status
    } = response;

    if (status >= 200 && status < 300) {
    return parsed;
    }

    return Promise.reject(new Error(parsed));
    };

    const test = () => {

    return checkStatus(res)
    .then(console.log)
    .catch((err) => console.warn(err.message))
    .finally(() => {
    if (res.status === 200) {
    res.status = 422;
    return test();
    }
    });

    };

    test();


    另外,既然你已经使用了 ES6 特性(通过箭头函数的存在来判断),为什么不一直使用语法糖 async / await 提供:
    (() => {
    try {
    const response = await 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"
    }
    });

    const parsed = await response.json(); //json method returns a Promise!

    const {
    status
    } = response;

    if (status === 201) {
    return successCallback(parsed);
    }

    throw new Error(parsed);

    } catch (error) {
    return errorCallback(error);
    }
    })();

    请注意,当您传递 parsed JSON 内容到 Error()构造函数,抽象 ToString调用操作(参见 ECMA 规范的 step 3a)。
    如果消息是一个对象,除非原始对象有 toString 方法,你会得到一个字符串标签,即 [object Object] ,导致错误处理程序无法访问对象的内容:

    (() => {

    const obj = { msg : "bang bang" };

    const err = new Error(obj);

    //will log [object Object]
    console.log(err.message);

    obj.toString = function () { return this.msg; };

    const errWithToString = new Error(obj);

    //will log "bang bang"
    console.log(errWithToString.message);

    })();

    相反,如果您 reject带有作为参数传递的对象的 Promise,被拒绝的 Promise 的 [[PromiseValue]]将是对象本身。

    关于javascript - 如果出现 HTTP 错误 422,如何使用 fetch 获取响应正文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63408816/

    46 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com