Javascript fetch:使用JSON错误对象拒绝承诺
我有一个HTTP API,在成功和失败时都返回JSON数据 失败示例如下所示:Javascript fetch:使用JSON错误对象拒绝承诺,javascript,promise,es6-promise,fetch-api,Javascript,Promise,Es6 Promise,Fetch Api,我有一个HTTP API,在成功和失败时都返回JSON数据 失败示例如下所示: ~ ◆ 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
~ ◆ 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"
}
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
}
我希望在JavaScript代码中实现以下目标:
~ ◆ 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"
}
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
}
fetch(url)
。然后((resp)=>{
如果(响应状态>=200&响应状态<300){
返回resp.json();
}否则{
//这是行不通的,因为“json()”返回的承诺从未兑现
return Promise.reject(resp.json());
}
})
.catch((错误)=>{
//对错误对象执行某些操作
}
好的,resp.json
承诺将得到履行,只有promise.reject
不会等待它并立即以承诺拒绝
我假设您希望执行以下操作:
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));
}
})
这里有一种更简洁的方法,它依赖并使用底层JSON数据,而不是
.JSON()
返回的Promise
函数myFetchWrapper(url){
返回获取(url)。然后(响应=>{
返回response.json().then(json=>{
return response.ok?json:Promise.reject(json);
});
});
}
//这将触发带有JSON响应的.then(),
//因为响应是HTTP 200。
myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn然后(console.log.bind(console));
//这将触发带有JSON响应的.catch(),
//因为响应是HTTP 400。
myFetchWrapper('https://content.googleapis.com/youtube/v3/search“).catch(console.warn.bind(console));
上面的解决方案是我最喜欢的方法,但是嵌套非常难看
使用较新的async/await语法,我们可以以一种更同步的方式来完成,而不会出现可能很快变得混乱的丑陋嵌套
async function myFetchWrapper(url) {
const response = await fetch(url);
const json = await response.json();
return response.ok ? json : Promise.reject(json);
}
这是因为,一旦有了JSON,我们就可以根据响应状态决定如何返回它(使用)
您可以使用与Jeff回答中相同的方法处理错误,但是您也可以使用try/catch、an或进行一些修改以防止拒绝承诺。您可以使用我最喜欢的技术来确保
同样值得一读的是,为什么我们必须这样做,本质上一个获取请求只会因为网络错误而被拒绝,获取一个404不是一个网络错误。你的意思是
json
方法返回一个Promise
?是的,根据工作组的fetch
规范:谢谢,这(差不多)成功了!我必须在匿名函数中包装Promise.reject,否则我会得到一个未定义的函数不是一个函数
错误,但是有了这个小改动它就可以工作了:-)嗯,你是不是懒得加载Promise?本机Promise.reject
永远不应该是undefined
。垫片是在应用程序启动时加载的,因此不应该延迟加载。我可以从调试器访问Promise.reject
也可以。以下是完整的跟踪:TypeError:undefined不是函数{stack:“TypeError:undefined不是函数↵ 在拒绝时(本机)”,消息:“未定义不是函数”}
在拒绝时?啊,它需要是。然后(Promise.reject.bind(Promise))
@torazaburo:No,json
在这里是一个承诺,我们不想用承诺来拒绝,而是用它的结果值。啊,。好的
看起来很有趣。然而,我不认为“底层JSON数据”的用法更干净。毕竟,您可以将其简化为fetch(url)。然后(response=>response.ok?response.json():response.json()。然后(err=>Promise.reject(err))
我的意思是让json=resp.json()代替
如果json
是一个Promise
,那么首先解析Promise
,然后使用它解析的数据可能会更简单。这两种方法都有效。我们试图拒绝嵌套的承诺,但不确定如何拒绝。事实证明,这只是对静态“拒绝”方法的调用。在我看来,这是一个比公认的答案好得多的答案。
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);
}