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

时间:2016-11-03 17:54:18

标签: 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));

            });


    }
}

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

所以这是我在收到错误时从网络标签中获得的内容。

enter image description here

我的控制台

enter image description here

这是我的导轨代码

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

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

谢谢!

6 个答案:

答案 0 :(得分:7)

好吧,我想我终于解决了这个问题。

文本隐藏在响应对象内的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);
    }

答案 1 :(得分:1)

尽管这是一个有点老的问题,我还是要补充一下。

在上面的评论中有这个答案:

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

当然,您可以使用它,但要记住一件重要的事情。如果您从其余 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))

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

.then(response => {
       if (response.ok) return response.json();
       return response.json().then(response => {throw new Error(response.error)})
})

如果响应没问题(即服务器返回 2xx 响应),它返回另一个承诺 response.json(),随后在下一个 then 块中处理。

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

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

呸!希望能帮到你!

我一直在寻找这个问题,并发现了这篇文章,所以我认为我的回答将来会对某人有所帮助。

祝你有美好的一天!

马雷克

答案 2 :(得分:0)

首先,您需要在响应中调用json方法。

一个例子:

fetch(`${API_URL}`, {
        method: 'post',
        headers: {
           'Accept': 'application/json',
           'Content-Type': 'application/json'
        },
        body: JSON.stringify(userInfoParams)
    })
    .then((response) => response.json())
    .then((response) => console.log(response)) 
    .catch((err) => {
        console.log("error", err) 
    });

如果控制台日志不适合您,请告诉我。

答案 3 :(得分:0)

与您的答案类似,但有更多解释......我首先检查响应是否正常,然后仅针对我们成功响应的情况从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)})
    })
}

然后当我使用它时,我定义了当时需要处理我的响应和错误的方法:

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)
  })

答案 4 :(得分:0)

我认为您需要做类似的事情

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());
            return response.json();
        })
        .then(function(object){
          if (object.errors) {
            dispatch(update_errors(response));
            throw new Error(object.errors);
          } else {
            console.log("succeed json re");
            dispatch(update_user(json));
          }
        })
        .catch(function(error){
          this.setState({ error })
        })
       }
     }

答案 5 :(得分:-1)

您回来的变量不在response.bodyresponse.message

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

if(response.errors) {
    console.error(response.errors)
}

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

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