简体   繁体   English

如何捕获 HTTP 响应错误,然后传递给调用者

[英]How to catch HTTP response error and then pass to the caller

I have an API to update data to the database.我有一个 API 来将数据更新到数据库。

I am using Fetch API to send data to the server API for storing data in the database.我正在使用 Fetch API 将数据发送到服务器 API 以将数据存储在数据库中。

In case the webserver cannot update data to the database, it returns a 500 error code and an error message.如果网络服务器无法将数据更新到数据库,它会返回 500 错误代码和错误消息。

And the response JSON as the following:响应 JSON 如下:

{"status":"error","message":"Some wrong when update roster data."}

My problem is that I cannot forward the message to the fetch API caller.我的问题是我无法将消息转发给 fetch API 调用者。

It is my fetch API source code:这是我获取的 API 源代码:

static async fetchAPI(url,method,getParams,postParams){
  if (getParams){
      const paramsObject = new URLSearchParams(getParams);
      const queryString = paramsObject.toString();  
      url+="?"+queryString;
  }
  url="/rosterWeb"+url;
  console.log("=======================");
  console.log("url="+url);
  console.log("method="+method);
  console.log("getParams="+getParams);
  console.log("postParams="+postParams);
  console.log("=======================");
  return fetch(url,
                {
                    body: JSON.stringify(postParams),
                    headers:{
                        'Content-Type': 'application/json' 
                    },
                    "method":method || 'GET',
                })
          .then(response =>{
            if (response.ok){
              return response.json();                
            } else {
              if (response.status===500){
                response.json()
                .then(json=>{
                  throw new Error(json.message);
                })
              }
            }  
          })
          .catch(error =>{
            console.error('Error:', error);
          });              
                

} }

This is my middleware code snippet:这是我的中间件代码片段:

import Utility from './Utility';
export default class Roster{
  ..............
  .......
  constructor(){
    this.saveToDB=async(data)=>{
        return await Utility.fetchAPI(*saveDataURL*,POST',null,rosterData);
    }
  }
}

This is my UI component code snippet:这是我的 UI 组件代码片段:

export default function ButtonPanel(){
 ..............................
 
 async function saveDataToDB(){
    
    let roster=new Roster();

    await roster.saveRosterToDB({
       ........................
       ...........................
    })
    .then(result=>{
        console.log("Update Success")
    })
    .catch(error=>{
        console.log("ButtonPanel Exception Caught");
        console.log(error);
    })
    /*
    try{
        let result=await roster.saveRosterToDB({
            month:rosterMonth.getMonth()+1,
            preferredShiftList:rosterData.preferredShiftList,
            rosterList:rosterData.rosterList,
            year:rosterMonth.getFullYear(),
        })
        console.log(result);
    }catch(error){
        console.log("Exception caught.");
        console.log(error.message);
    };
    */
    roster=null;
  }
}

When I execute the Roster.saveRosterToDB method, both try-catch and then-catch structure, it also returns the following error:当我执行 Roster.saveRosterToDB 方法时,try-catch 和 then-catch 结构,它也返回以下错误:

`Unhandled Rejection (Error): Some wrong when update roster data.
(anonymous function)
c:/Users/knvb/workspace/rosterWeb_react_node/src/utils/Utility.js:91`

Where "Some wrong when update roster data" is come from response JSON. “更新名册数据时出现一些错误”来自响应 JSON。

And the ButtonPanel.saveDataToDB print the statement "Update success" to the console.并且 ButtonPanel.saveDataToDB 将语句“更新成功”打印到控制台。

I tried to forward the message from the server to ButtonPanel via an exception.我试图通过异常将消息从服务器转发到 ButtonPanel。

However, the exception/error does not be triggered, how can I fix it?但是,没有触发异常/错误,我该如何解决?

Seems like return was missing in 500 status handling block似乎在 500 状态处理块中缺少return

          fetch(url,
                {
                    body: JSON.stringify(postParams),
                    headers:{
                        'Content-Type': 'application/json' 
                    },
                    "method":method || 'GET',
                })
          .then(response =>{
            if (response.ok){
              return response.json();                
            } else {
              if (response.status===500){
                return response.json() // return was missing here
                .then(json=>{
                  throw new Error(json.message);
                })
              }
            }  
          })
          .catch(error =>{
            console.error('Error:', error);
          });     

The code above during 500 status will return a promise.上面的代码在 500 状态下将返回 promise。

It'll first get the JSON payload from 500 response and will throw an error with the message from JSON, which will mean that returned promise will become rejected and all catch blocks attached to that promise (including the one with console.error() ) will be called. It'll first get the JSON payload from 500 response and will throw an error with the message from JSON, which will mean that returned promise will become rejected and all catch blocks attached to that promise (including the one with console.error() )将被调用。

The main problem is that the place you're doing throw new Error(json.message) just causes a rejection of the promise from the fulfillment handler it's in, but that promise isn't connected to the chain you have a catch on.主要问题是你正在做的地方throw new Error(json.message)只会导致 promise 从它所在的履行处理程序中被拒绝,但是 promise 没有连接到你有catch的链。 It would be if you added return .如果你添加了return Eg, change:例如,改变:

response.json()
    .then(json => {
        throw new Error(json.message);
    })

to

return response.json()
    .then(json => {
        throw new Error(json.message);
    })

But there are a few other issues:但还有一些其他问题:

  1. fetchAPI is an async function, so there's no reason to be using .then and .catch in it. fetchAPI是一个async function,所以没有理由在其中使用.then.catch Use await .使用await

  2. What if response.ok is false but response.status isn't 500?如果response.ok为 false 但response.status不是 500 怎么办? Your code falls through and ends up fulfilling the promise from fetchAPI with undefined with no indication of why it hasn't returned anything.您的代码失败并最终通过undefinedfetchAPI完成 promise ,但没有说明为什么它没有返回任何内容。 It should raise some kind of error in that case as well.在这种情况下,它也应该引发某种错误。

  3. fetchAPI hides all errors, disguising them as results with the value undefined , because of the catch handler at the end. fetchAPI隐藏所有错误,将它们伪装成值为undefined的结果,因为最后的catch处理程序。 That's an anti-pattern.这是一种反模式。 Don't handle errors in fetchAPI , handle them where it's used , so that the code where it's used knows whether the operation succeeded or failed.不要在fetchAPI中处理错误,在使用的地方处理它们,以便使用它的代码知道操作是成功还是失败。

Here's how I'd suggest you update fetchAPI :以下是我建议您更新fetchAPI的方法:

static async fetchAPI(url, method, getParams, postParams) {
    if (getParams) {
        const paramsObject = new URLSearchParams(getParams);
        const queryString = paramsObject.toString();
        url += "?" + queryString;
    }
    url = "/rosterWeb" + url;
    console.log("=======================");
    console.log("url=" + url);
    console.log("method=" + method);
    console.log("getParams=" + getParams);
    console.log("postParams=" + postParams);
    console.log("=======================");
    const response = await fetch(url, {
        body: JSON.stringify(postParams),
        headers: {
            'Content-Type': 'application/json'
        },
        "method": method || 'GET',
    });
    if (response.status === 500) {
        const error = await response.json();
        throw new Error(error.message);
    } else if (!response.ok) {
        throw new Error(`HTTP error ${response.status}`);
    }
    return response.json();
}

When using it, if its promise is fulfilled, you know it's the data from the API.使用时,如果它的promise被满足,就知道是API的数据了。 If its promise is rejected, you know it isn't the data from the API and that you should handle/report an error.如果它的 promise 被拒绝,您知道这不是来自 API 的数据,您应该处理/报告错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM