【问题标题】:How to catch HTTP response error and then pass to the caller如何捕获 HTTP 响应错误,然后传递给调用者
【发布时间】:2021-03-12 16:20:29
【问题描述】:

我有一个 API 可以将数据更新到数据库中。

我正在使用 Fetch API 将数据发送到服务器 API 以将数据存储在数据库中。

如果网络服务器无法将数据更新到数据库,它会返回 500 错误代码和错误消息。

响应 JSON 如下:

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

我的问题是我无法将消息转发给 fetch API 调用者。

这是我的 fetch 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);
          });              
                

}

这是我的中间件代码 sn-p:

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

这是我的 UI 组件代码 sn-p:

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

当我执行 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`

“更新名册数据时出现一些错误”来自响应 JSON。

ButtonPanel.saveDataToDB 将语句“更新成功”打印到控制台。

我试图通过异常将消息从服​​务器转发到 ButtonPanel。

但是,异常/错误没有被触发,我该如何解决?

【问题讨论】:

  • 我将相关信息添加到我的问题文本中。请检查。
  • 我建议您查看 axios 的 XHR。我通常发现它比fetch api 更容易使用,并且更容易编码。它也有大量的追随者。我很感激这并不能完全回答您的问题,但它会让事情变得更容易。

标签: javascript reactjs fetch


【解决方案1】:

似乎return 在 500 状态处理块中丢失了

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

上面的代码在 500 状态下会返回一个 promise。

它将首先从 500 响应中获取 JSON 有效负载,并会在来自 JSON 的消息中抛出错误,这意味着返回的承诺将被拒绝,并且所有附加到该承诺的 catch 块(包括带有 @ 的块) 987654324@) 将被调用。

【讨论】:

    【解决方案2】:

    主要问题是您正在做的地方throw new Error(json.message) 只会导致它所在的履行处理程序拒绝承诺,但该承诺没有连接到您拥有catch 的链。如果您添加了return。例如,改变:

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

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

    但还有一些其他问题:

    1. fetchAPI 是一个async 函数,因此没有理由在其中使用.then.catch。使用await

    2. 如果response.ok 为假但response.status 不是 500 怎么办?您的代码失败并最终履行了来自fetchAPIundefined 的承诺,但没有说明为什么它没有返回任何内容。在这种情况下,它也会引发某种错误。

    3. fetchAPI 隐藏所有错误,将它们伪装成值为undefined 的结果,因为末尾有catch 处理程序。这是一种反模式。 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();
    }
    

    使用它时,如果它的承诺得到履行,你就知道它是来自 API 的数据。如果它的承诺被拒绝,你就知道它不是来自 API 的数据,你应该处理/报告错误。

    【讨论】:

      猜你喜欢
      • 2018-09-23
      • 2015-11-17
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      • 2017-03-27
      相关资源
      最近更新 更多