如何从javascript Fetch api获取可读错误响应?

Var*_*kul 8 javascript reactjs fetch-api

我正在研究前端的Reactjs redux和后端的Rails api.

所以现在我用Fetch api方法调用api,但问题是我无法获得可读的错误信息,就像我在网络选项卡中得到的一样

这是我的功能

export function create_user(user,userInfoParams={}) {

    return function (dispatch) {
        dispatch(update_user(user));

        return fetch(deafaultUrl + '/v1/users/',
            {
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                method: "POST",
                body: JSON.stringify(userInfoParams)
            })
            .then(function(response) {
                console.log(response);
                console.log(response.body);
                console.log(response.message);
                console.log(response.errors);
                console.log(response.json());
                dispatch(update_errors(response));

                if (response.status >= 400) {
                    throw new Error("Bad response from server");
                }

            })
            .then(function(json){
                console.log("succeed json re");
                // We can dispatch many times!
                // Here, we update the app state with the results of the API call.

                dispatch(update_user(json));

            });


    }
}
Run Code Online (Sandbox Code Playgroud)

但是当出现错误时,我无法弄清楚如何获得可读的响应消息,就像我在浏览器网络选项卡上查看时一样

这就是我遇到错误时从网络选项卡中获得的内容.

在此输入图像描述

我的控制台

在此输入图像描述

这是我的rails代码

def create
    user = User.new(user_params)
    if user.save
      #UserMailer.account_activation(user).deliver_now
      render json: user, status: 201
    else
      render json: { errors: user.errors }, status: 422
    end
  end
Run Code Online (Sandbox Code Playgroud)

但我无法找到我如何在我的功能中得到它

谢谢!

Mar*_*nec 20

尽管这是一个有点老的问题,但我还是要插话。

上面的评论里有这样的答案:

const fetchJSON = (...args) => {
  return fetch(...args)
    .then(res => {
      if(res.ok) {
        return res.json()
      }
      return res.text().then(text => {throw new Error(text)})
    })
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用它,但有一件重要的事情需要记住。如果您从其余 api 返回 json,看起来像{error: 'Something went wrong'},上面显示的代码return res.text().then(text => {throw new Error(text)})肯定会工作,但res.text()实际上返回的是字符串。是的,你猜对了!字符串不仅包含值,还包含合并在一起的键!这让你别无选择,只能以某种方式将其分开。哎呀!

因此,我提出了一个不同的解决方案。

fetch(`backend.com/login`, {
   method: 'POST',
   body: JSON.stringify({ email, password })
 })
 .then(response => {
   if (response.ok) return response.json();
   return response.json().then(response => {throw new Error(response.error)})
 })
 .then(response => { ...someAdditional code })
 .catch(error => reject(error.message))
Run Code Online (Sandbox Code Playgroud)

那么让我们来破解代码,then特别是第一个。

.then(response => {
       if (response.ok) return response.json();
       return response.json().then(response => {throw new Error(response.error)})
})
Run Code Online (Sandbox Code Playgroud)

如果响应正常(即服务器返回 2xx 响应),它会返回另一个 Promise response.json(),该 Promise 会在下一个then块中随后处理。

否则,我将再次调用response.json()方法,但也会为其提供自己的then代码块。在那里我会抛出一个新的错误。在本例中,括号中的响应throw new Error(response.error)是一个标准的 javascript 对象,因此我将从中获取错误。

catch正如您所看到的,最后还有一个代码块,您可以在其中处理新抛出的错误。(error.message<-- 错误是一个由许多字段(例如名称或消息)组成的对象。在这个特定实例中我没有使用名称。无论如何,您一定有这些知识)

哒哒哒!希望能帮助到你!

我一直在研究这个问题,并发现了这篇文章,所以我认为我的答案将来会对某人有益。

祝你愉快!

马雷克


Sia*_*Sia 10

与您的答案类似,但有更多解释......我首先检查响应是否正常,然后response.text()仅针对我们成功响应的情况生成错误。因此,网络错误(不是ok)仍会生成自己的错误而不会转换为文本。然后这些错误在下游被捕获catch

这是我的解决方案 - 我将核心提取函数拉入包装函数中:

const fetchJSON = (...args) => {
  return fetch(...args)
    .then(res => {
      if(res.ok) {
        return res.json()
      }
      return res.text().then(text => {throw new Error(text)})
    })
}
Run Code Online (Sandbox Code Playgroud)

然后当我使用它时,我会根据当时的需要定义如何处理我的响应和错误:

fetchJSON(url, options)
  .then((json) => {
    // do things with the response, like setting state:
    this.setState({ something: json })
  })
  .catch(error => {
    // do things with the error, like logging them:
    console.error(error)
  })
Run Code Online (Sandbox Code Playgroud)


Mar*_*als 7

好的,我想我终于破解了。

文本隐藏在响应对象内的promise中,因此需要像看待promise一样处理它。

fetch(bla)
    .then(res => {
      if(!res.ok) {
        res.text().then(text => throw Error(text))
       }
      else {
       return res.json();
     }    
    })
    .catch(err => {
       console.log('caught it!',err);
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果您从服务器收到 400 响应,您将收到错误:res.text is not a function。为了避免这种情况,您必须使用 `try{...} catch{...}` 函数。 (5认同)

oct*_*ron 5

如果您在尝试查找问题时遇到这个问题,因为response.json()抛出了异常"Unexpected token at position...",并且无法找到 JSON 的问题,那么您可以尝试这个,基本上是获取文本,然后解析它

fetch(URL)
  .then(async (response) => {
    if (!response.ok) {
      const text = await response.text()
      throw new Error(text)
    }
    // Here first we convert the body to text
    const text = await response.text()
    // You can add a console.log(text), to see the response
    // Return the JSON
    return JSON.parse(text)
  })
  .catch((error) => console.log('Error:', error))
  .then((response) => console.log(response))
Run Code Online (Sandbox Code Playgroud)


小智 -3

您返回的变量不在response.bodyor中response.message

您需要检查响应对象上的错误属性。

if(response.errors) {
    console.error(response.errors)
}
Run Code Online (Sandbox Code Playgroud)

检查此处https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

您实际上应该从服务器返回错误响应代码并使用.catch()fetch API 的功能