Fetch api - 在 then 和 catch 块中获取 json 主体以获取单独的状态代码
Posted
技术标签:
【中文标题】Fetch api - 在 then 和 catch 块中获取 json 主体以获取单独的状态代码【英文标题】:Fetch api - getting json body in both then and catch blocks for separate status codes 【发布时间】:2017-01-13 08:26:20 【问题描述】:我正在使用 fetch api 来获取可能返回的 URL:
响应:status = 200, json body = 'user': 'abc', 'id': 1
或
响应:status = 400,json body = 'reason': 'some reason'
或
响应:status = 400,json body = 'reason': 'some other reason'
我想创建一个单独的函数request()
,我从代码的各个部分使用它,如下所示:
request('http://api.example.com/').then(
// status 200 comes here
data => // do something with data.id, data.user
).catch(
// status 400, 500 comes here
error => // here error.reason will give me further info, i also want to know whether status was 400 or 500 etc
)
我无法在 200 和 400,500 之间进行分割(我尝试过抛出错误)。当我抛出错误时,我发现仍然很难提取 JSON 正文(用于 error.reason)。
我目前的代码如下:
import 'whatwg-fetch';
/**
* Requests a URL, returning a promise
*/
export default function request(url, options=)
console.log('sending api request, url = ' + url)
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then((data) => (data))
.catch((err) => (err));
function checkStatus(response)
if (response.status >= 200 && response.status < 300)
return response;
const error = new Error(response.statusText);
error.response = response;
throw error;
function parseJSON(response)
return response.json(); // json() is a promise itself
我尝试通过以下方法解决此问题,方法是颠倒.then()
调用的顺序,但不起作用
export default function request(url, options)
return fetch(url, options)
.then(parseJSON) // note that now first calling parseJSON to get not just JSON but also status.
.then(checkStatus) // i.e. Inverted order of the two functions from before
.then((data) => (data))
.catch((err) => (err));
function checkStatus(data, status)
if (status >= 200 && status < 300)
return data;
else
// const error = new Error(response.statusText);
const error = new Error("Something went wrong");
// error.response = response;
error.data = data;
throw error;
function parseJSON(response)
let jsonBody
response.json().then(json =>
jsonBody = json // this does not help, i thought it will make jsonBody fill up, but seems its in a diff thread
)
return
data: jsonBody,
status: response.status // my aim is to send a whole dict with status and data to send it to checkStatus, but this does not work
【问题讨论】:
错误出现在 .then 的第二个回调中 ->request('http://api.example.com/').then( function(data) //success call back, i.e 200 , function( jqXHR, textStatus, errorThrown) // error call back. Check the status code here );
this does not help
- 该代码的问题是 Promises 不会使异步代码同步(代码假定它们会同步)
与Cleanest way to handle custom errors with fetch & ES6 promise 或fetch: Reject promise with JSON error object 重复?
【参考方案1】:
response.json()
返回一个异步结果。您不会从链接到response.json()
的.then()
中返回parseJSON
的对象。要纠正这个问题,您可以在 parseJSON
调用中返回 response.json()
承诺,并从链接到 response.json()
的 .then()
中返回包含 data
和 status
的对象
function parseJSON(response)
return response.json().then(json =>
return
data: json,
status: response.status
)
【讨论】:
您实际上可以将该函数体缩短为return response.json().then(json => ( data: json, status: response.status ));
@JaromandaX 是的,不想让 Answer 上的问题进一步复杂化
看起来 OP 对箭头函数足够熟悉,甚至可以做 var parseJSON = response => response.json().then(json => ( data: json, status: response.status ));
【参考方案2】:
这里有一个稍微不同的方法:我使用单行创建一个带有 ok、status 和 json-as-object(不是承诺)的类似响应的承诺,然后我决定如何处理这个对象。通常,如果 response.ok 为 false,我会拒绝响应,否则我仅使用 json-data 解决。网络错误/json-parse-errors 像往常一样被拒绝。
fetch(url, options)
.then(r => r.json().then(json => (ok: r.ok, status: r.status, json)))
.then( r => r.ok ? r.json: Promise.reject(r))
【讨论】:
据我所知,使用带有响应的扩展运算符不起作用,但会导致未定义。所以你的 es6 例子是错误的。你能确认一下吗? @webwelten:你说得对,我不知道我为什么写这个。我相信当我编写它时它对我有用(我通常在发布之前测试代码)。但是,该代码(现在已废弃)经历了编译步骤(babel 和/或打字稿,如果我没记错的话)到旧式 JS,所以也许这就是原因。我将从答案中删除该行。以上是关于Fetch api - 在 then 和 catch 块中获取 json 主体以获取单独的状态代码的主要内容,如果未能解决你的问题,请参考以下文章