Javascript fetch:拒绝带有 JSON 错误对象的承诺
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29473426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
fetch: Reject promise with JSON error object
提问by jbaiter
I have an HTTP API that returns JSON data both on success and on failure.
我有一个 HTTP API,它在成功和失败时都返回 JSON 数据。
An example failure would look like this:
示例失败如下所示:
~ ◆ http get http://localhost:5000/api/isbn/2266202022
HTTP/1.1 400 BAD REQUEST
Content-Length: 171
Content-Type: application/json
Server: TornadoServer/4.0
{
"message": "There was an issue with at least some of the supplied values.",
"payload": {
"isbn": "Could not find match for ISBN."
},
"type": "validation"
}
What I want to achieve in my JavaScript code is something like this:
我想在我的 JavaScript 代码中实现的是这样的:
fetch(url)
.then((resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp.json();
} else {
// This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());
}
})
.catch((error) => {
// Do something with the error object
}
回答by Bergi
// This does not work, since the Promise returned by `json()` is never fulfilled return Promise.reject(resp.json());
// This does not work, since the Promise returned by `json()` is never fulfilled return Promise.reject(resp.json());
Well, the resp.jsonpromise willbe fulfilled, only Promise.rejectdoesn't wait for it and immediately rejects with a promise.
那么,resp.jsonpromise将被实现,只是Promise.reject不等待它并立即使用 promise拒绝。
I'll assume that you rather want to do the following:
我假设您更愿意执行以下操作:
fetch(url).then((resp) => {
let json = resp.json(); // there's always a body
if (resp.status >= 200 && resp.status < 300) {
return json;
} else {
return json.then(Promise.reject.bind(Promise));
}
})
(or, written explicitly)
(或者,明确地写)
return json.then(err => {throw err;});
回答by Jeff Posnick
Here's a somewhat cleaner approach that relies on response.okand makes use of the underlying JSON data instead of the Promisereturned by .json().
下面是依赖于一定程度上更简洁的方法response.ok,并利用底层的JSON数据,而不是的Promise由归国.json()。
function myFetchWrapper(url) {
return fetch(url).then(response => {
return response.json().then(json => {
return response.ok ? json : Promise.reject(json);
});
});
}
// This should trigger the .then() with the JSON response,
// since the response is an HTTP 200.
myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));
// This should trigger the .catch() with the JSON response,
// since the response is an HTTP 400.
myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));
回答by tomhughes
The solution above from Jeff Posnickis my favourite way of doing it, but the nesting is pretty ugly.
上面来自Jeff Posnick的解决方案是我最喜欢的方法,但是嵌套非常难看。
With the newer async/awaitsyntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.
使用较新的async/await语法,我们可以以更同步的方式进行操作,而不会出现可能很快令人困惑的丑陋嵌套。
async function myFetchWrapper(url) {
const response = await fetch(url);
const json = await response.json();
return response.ok ? json : Promise.reject(json);
}
This works because, an async function always returns a promiseand once we have the JSON we can then decide how to return it based on the response status (using response.ok).
这是有效的,因为异步函数总是返回一个承诺,一旦我们有了 JSON,我们就可以根据响应状态决定如何返回它(使用response.ok)。
You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an error handling higher order function.
您将以与 Jeff 的答案相同的方式进行错误处理,或者您可以使用 try/catch,甚至错误处理高阶函数。
const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'
// Example with Promises
myFetchWrapper(url)
.then((res) => ...)
.catch((err) => ...);
// Example with try/catch (presuming wrapped in an async function)
try {
const data = await myFetchWrapper(url);
...
} catch (err) {
throw new Error(err.message);
}
Also worth reading MDN - Checking that the fetch was successfulfor why we have to do this, essentially a fetch request only rejects with network errors, getting a 404 is not a network error.
还值得一读MDN - 检查获取是否成功,因为我们必须这样做,本质上,获取请求只会因网络错误而被拒绝,获得 404 不是网络错误。

