当 return 代码不是 200 时如何抛出响应?
How to throw a Response when the return code is not 200?
我正在为我的 API 调用编写一个助手,希望它能
- 调用成功时传递
text()
响应
- 抛出 完整响应 否则
原因是我有一个 API 调用的案例,其中预期 404
并且想要管理这个特定案例。其他404
(在不同的调用中)确实是错误的。
考虑以下代码:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw Error(r.statusText) // this works but is not what I want, I want to throw "r"
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err}`)) // this works but I obviously got a statusText and not an r
这输出
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was Error: Not Found
200 OK
我想要做的是一次调用,其中需要404
(在上面代码的上下文中这是不正确的代码)
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
if (err.Code == 404) {
// it is OK
} else {
// it is not OK
}
})
对于任何非 2xx 响应不正确的另一个调用:
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
// not OK
})
我怎样才能 throw
响应而不仅仅是文本?
换句话说,我想要的代码:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw r
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err // I would need to manage actual errors (network, ...)
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.Code}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.Code}`))
但这会输出 undefined
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was undefined
200 OK
可以添加参数为expectedFailureCodes
,失败后查看请求码。如果是意料之中的,那你可以随意处理。
import fetch from "node-fetch";
const apiCall = (url, expectedFailureCodes=[]) => {
return fetch(url)
.then(async res => {
if (res.ok) return res
else if (expectedFailureCodes.includes(res.status)) {
return {
passedIntentionally: true,
res
}
}
else throw new Error(JSON.stringify({
status: res.status,
body: await res.text()
}))
})
.catch(err => {
throw err
})
}
apiCall("http://httpstat.us/404", [404]).then(res => {
console.log(res)
})
apiCall("http://httpstat.us/404", ).catch(err => {
console.log(err)
})
apiCall("http://httpstat.us/200", ).then(res => {
console.log(res)
})
好吧,throw
ing r
工作正常,你只是记录了错误的 属性。可以通过 r.status
:
访问状态代码
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw r
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err // I would need to manage actual errors (network, ...)
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.status}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.status}`))
该方法的唯一问题是,您的代码不知道如何处理“硬错误”(代码中的网络错误或运行时错误)。你可以用“鸭子打字方法”来识别那些(如果它有一个 status
属性,它必须是一个 Response 对象......),但更好的解决方案是有一个自定义错误 class:
class HTTPError extends Error{
constructor(r){
super(`HTTP ${r.status} error`)
this.r = r
}
}
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw new HTTPError(r)
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => {
if(!(err instanceof HTTPError))
throw err //Other error
console.log(`the return code was ${err.r.status}`)
})
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
if(!(err instanceof HTTPError))
throw err //Other error
//You can access `r` via `err.r` here
console.log(`the return code was ${err.r.status}`)
})
我正在为我的 API 调用编写一个助手,希望它能
- 调用成功时传递
text()
响应 - 抛出 完整响应 否则
原因是我有一个 API 调用的案例,其中预期 404
并且想要管理这个特定案例。其他404
(在不同的调用中)确实是错误的。
考虑以下代码:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw Error(r.statusText) // this works but is not what I want, I want to throw "r"
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err}`)) // this works but I obviously got a statusText and not an r
这输出
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was Error: Not Found
200 OK
我想要做的是一次调用,其中需要404
(在上面代码的上下文中这是不正确的代码)
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
if (err.Code == 404) {
// it is OK
} else {
// it is not OK
}
})
对于任何非 2xx 响应不正确的另一个调用:
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
// not OK
})
我怎样才能 throw
响应而不仅仅是文本?
换句话说,我想要的代码:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw r
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err // I would need to manage actual errors (network, ...)
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.Code}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.Code}`))
但这会输出 undefined
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was undefined
200 OK
可以添加参数为expectedFailureCodes
,失败后查看请求码。如果是意料之中的,那你可以随意处理。
import fetch from "node-fetch";
const apiCall = (url, expectedFailureCodes=[]) => {
return fetch(url)
.then(async res => {
if (res.ok) return res
else if (expectedFailureCodes.includes(res.status)) {
return {
passedIntentionally: true,
res
}
}
else throw new Error(JSON.stringify({
status: res.status,
body: await res.text()
}))
})
.catch(err => {
throw err
})
}
apiCall("http://httpstat.us/404", [404]).then(res => {
console.log(res)
})
apiCall("http://httpstat.us/404", ).catch(err => {
console.log(err)
})
apiCall("http://httpstat.us/200", ).then(res => {
console.log(res)
})
好吧,throw
ing r
工作正常,你只是记录了错误的 属性。可以通过 r.status
:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw r
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err // I would need to manage actual errors (network, ...)
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.status}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.status}`))
该方法的唯一问题是,您的代码不知道如何处理“硬错误”(代码中的网络错误或运行时错误)。你可以用“鸭子打字方法”来识别那些(如果它有一个 status
属性,它必须是一个 Response 对象......),但更好的解决方案是有一个自定义错误 class:
class HTTPError extends Error{
constructor(r){
super(`HTTP ${r.status} error`)
this.r = r
}
}
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw new HTTPError(r)
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => {
if(!(err instanceof HTTPError))
throw err //Other error
console.log(`the return code was ${err.r.status}`)
})
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
if(!(err instanceof HTTPError))
throw err //Other error
//You can access `r` via `err.r` here
console.log(`the return code was ${err.r.status}`)
})