【问题标题】:fetch() not catching custom error messagefetch() 未捕获自定义错误消息
【发布时间】:2021-06-01 06:21:55
【问题描述】:

我有以下 fetch() api,但 catch 块无法正常工作。我得到的错误信息是:

SyntaxError: Unexpected token < in JSON at position 0 undefined

但我期待的是:

something went wrong null

这里是 api:

const getBtn = document.getElementById('get-btn')
const postBtn = document.getElementById('post-btn')


const sendHttpRequest = (method, url, data) => {
    return fetch(url, {
        method: method,
        body: JSON.stringify(data),
        headers: data ? {'Content-Type': 'application/json'} : {}
    })
        .then(response => {
            console.log(response.status)
            if(response.status >= 400 || response == null){
                return response.json()
                    .then(errResData => {
                        const error = new Error('something went wrong')
                        error.data = errResData
                        throw error;
                    })
            }
            return response.json()
    })
}

const getData = () =>{
    sendHttpRequest('GET','http://localhost/async/fetch/data.jsonx')
        .then(responseData => {
            console.log(responseData)
        })
        .catch(err =>{
            console.log(err,err.data)
        })

}

const sendData = () =>{
    sendHttpRequest('POST','http://localhost/async/fetch/data.phpx',{
        email: 'someemail@gmail.com',
        password: 'compas'
    })
        .then(responseData => {
            console.log(responseData)
        })
        .catch(err => {
            console.log(err,err.data)
        })
}


getBtn.addEventListener('click',getData)
postBtn.addEventListener('click',sendData)

【问题讨论】:

  • .then(errResData =&gt; { 如果你想捕获错误,你需要.catch(errResData =&gt; {...
  • 可能是 404,而不是像代码所期望的那样返回 json,而是返回 html?通常 html 文档中的第一个字符是&lt;,因此会出现错误。 (虽然看data.phpx,可能是&lt;?php
  • 我猜response.json() 失败了,而你永远不会catch 那个
  • localhost/async/fetch/data.jsonx 看到你有什么,我很确定那里有一些 HTML 而不是 JSON。
  • @robo Robok 实际的 url 是 localhost/async/fetch/data.json 或 data.php。我在两者上都添加了一个 x 以创建 404 错误

标签: javascript fetch-api catch-block


【解决方案1】:

为了查看正文是否可解析为 JSON,您需要在 Promise 上调用 .json。这将返回一个 Promise,该 Promise 要么解析为解析值,要么由于 body 不可解析而抛出。

如果它不可解析,连接到它的.thens 将不会运行;如果正文不可解析, return response.json().then 将不起作用,因此解释器永远不会到达 new Error('something went wrong')

.then(response => {
    console.log(response.status)
    if(response.status >= 400 || response == null){
        return response.json()
            .then(errResData => {
                const error = new Error('something went wrong')
                error.data = errResData
                throw error;
            })
    }
    return response.json()

应该是

.then(response => {
    console.log(response.status)
    if(response.status >= 400 || response == null){
        return response.json()
            .catch(errResData => {
                const error = new Error('something went wrong')
                error.data = errResData
                throw error;
            })
    }
    return response.json()

如果不可解析的响应总是满足条件response.status &gt;= 400 || response == null

编辑后的代码中.catch里面的throw error会导致Promise被拒绝,所以getData.catch会看到错误。

【讨论】:

  • 我遵循您的建议,但相信您可能忽略了一个潜在问题。如果我们有错误但 response.json() 返回会发生什么。我认为我们需要一个 .then 和一个 .catch
  • 你是什么意思,but response.json() returns?如果根据您的问题,您要在此处捕获的错误消息是 SyntaxError: Unexpected token &lt; in JSON at position 0 undefined,那么添加 .catch 而不是 .then 将正确捕获无法解析的 JSON。
  • 是的,这是真的,但这只是因为 response.json() 不起作用。假设返回的响应为 null,则永远不会调用 throw 错误,因为它处于 catch 而不是 then
  • .json 不起作用只是因为响应不是 JSON 可解析的。 fetch 无论如何都不能返回 null - 它总是一个 Response 类型的对象。如果您想检查解析结果是否为空,请在调用 .json 之后在 another .then 中执行此操作 - 但这很奇怪,可能应该由调用者处理跨度>
【解决方案2】:

如果你想从 Promise 中捕获错误,你应该使用 .catch() 而不是 .then()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 2017-10-03
    • 1970-01-01
    • 2018-09-29
    相关资源
    最近更新 更多