首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当返回代码不是200时,如何抛出响应?

当返回代码不是200时,如何抛出响应?
EN

Stack Overflow用户
提问于 2022-03-13 14:03:17
回答 2查看 1.1K关注 0票数 0

我正在为我的API调用编写一个助手,并且希望它能够

当调用为successful

  • throw时,
  • 传递text()响应,否则为完全响应,否则为

这样做的原因是我有一个API调用的例子,其中期望有一个404,并且希望管理这个特定的情况。其他404 (在不同的调用中)确实是错误。

考虑下面的守则:

代码语言:javascript
复制
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

这输出

代码语言:javascript
复制
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的调用(在上面的代码上下文中这是不正确的代码)。

代码语言:javascript
复制
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响应不正确的另一个呼叫:

代码语言:javascript
复制
apiCall('http://httpstat.us/404')
  .then(r => console.log(r))
  .catch(err => {
   // not OK
  })

我怎样才能throw 的响应,而不仅仅是文本?

换句话说,我想要的代码:

代码语言:javascript
复制
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

代码语言:javascript
复制
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was undefined
200 OK
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-03-13 14:48:13

嗯,throwing r工作正常,您只是记录了错误的属性。状态代码可以通过r.status访问。

代码语言:javascript
复制
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属性,它必须是响应对象.)来标识这些方法,但是更好的解决方案是有一个自定义错误类:

代码语言:javascript
复制
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}`)
  })  

票数 1
EN

Stack Overflow用户

发布于 2022-03-13 14:20:03

可以将参数添加为expectedFailureCodes,并在请求代码失败后进行检查。如果它是很好的期望,那么你可以处理它,你喜欢。

代码语言:javascript
复制
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)
})
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71457498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档