【问题标题】:Handling response status using fetch in react JS在 React JS 中使用 fetch 处理响应状态
【发布时间】:2018-09-18 09:12:49
【问题描述】:

我刚开始学习 ReactJS。现在我想知道当我使用 fetch 发出 API 请求时如何处理响应状态。这是我的代码:

componentDidMount(){
    this.setState({ isLoading: true })
    var id = this.props.match.params.id        

    const api = `bla/bla/${id}`;

    console.log("start call api")
    fetch(api)
        .then((response) => {
            if(response.status === 200){
                console.log("SUCCESSS")
                return response.json();     
            }else if(response.status === 408){
                console.log("SOMETHING WENT WRONG")
                this.setState({ requestFailed: true })
            }
        })
        .then((data) => {
            this.setState({ isLoading: false, downlines: data.response })
            console.log("DATA STORED")
        })
        .catch((error) => {
            this.setState({ requestFailed: true })
        })
    console.log("end call api")
}

我关闭了连接以测试408,但我的加载仍然出现。

render(){
     const { isLoading, requestFailed } = this.state;
      if(requestFailed){
        return( 
            <div className="errorContainer">
                <a className="errorMessage">Opss.. Something went wrong :(</a>
            </div>
        )
    }
}

这是我浏览器中的日志:

有什么办法可以解决这个问题吗?

【问题讨论】:

  • 你能看到实际的状态编号吗?不一定是每个错误都是 408
  • 检查response.ok 可能会更可靠。
  • @CertainPerformance 如果没有连接或请求超时等其他响应呢?
  • @kurniawan26 那么响应就不行了

标签: javascript reactjs fetch-api


【解决方案1】:

当响应不正确时抛出错误,以便它直接进入catch

fetch(api)
  .then((response) => {
    if(!response.ok) throw new Error(response.status);
    else return response.json();
  })
  .then((data) => {
    this.setState({ isLoading: false, downlines: data.response });
    console.log("DATA STORED");
  })
  .catch((error) => {
    console.log('error: ' + error);
    this.setState({ requestFailed: true });
  });

【讨论】:

    【解决方案2】:

    根据 MDN 文档:

    https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

    当遇到网络错误或 CORS 在服务器端配置错误时, fetch() 承诺将拒绝并返回 TypeError,尽管这通常意味着权限问题或类似问题——例如,404 并不构成网络错误。对成功的 fetch() 的准确检查将包括检查 promise 是否已解决,然后检查 Response.ok 属性的值是否为 true。代码看起来像这样:

    fetch('flowers.jpg').then(function(response) {
       if(response.ok) {
         return response.blob();
     }
     throw new Error('Network response was not ok.');
    }).then(function(myBlob) { 
       var objectURL = URL.createObjectURL(myBlob); 
       myImage.src = objectURL; 
    }).catch(function(error) {
     console.log('There has been a problem with your fetch operation: ', 
     error.message);
    });
    

    查看您的代码,我认为您的 408 错误检查永远不会运行。我认为事实上并没有。如果请求是 200ish ok,上面的代码基本上是返回 json 响应,否则它会抛出错误。如果发生错误,您的第二个则永远不会运行,它会被抛出到您的 catch 块。也许你可以在那里设置 isLoading: false ?

    另外,您的 api 结束日志语句也不正确。这是在你的承诺完成之前调用的。

    【讨论】:

    • 谢谢...你的声明Perhaps you can set the isLoading: false there?救救我..谢谢:D
    【解决方案3】:

    如果你想在同一个返回值中同时知道json响应和错误码,我推荐这种方法:

    async function loginUser(credentials) {
      var resp;
      return fetch("http://127.0.0.1:8000/api/token-auth/", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(credentials)
      }).then(response => {
        resp = response;
        return response.json();
      }).then(json => {
        return {
          response: resp,
          json: json,
          error: !resp.ok
        };
      });
    }
    

    在这种情况下,您将获得一个包含responsejsonerror 字段的数组。如果您使用带有每个字段错误消息的 API,这是一种更好的方法:

    {"username":["This field is required."],"password":["This field is required."]}
    

    【讨论】:

      【解决方案4】:

      如果您想同时捕获响应的状态代码和响应的正文,您可以使用此模式。对于我的项目,我创建了一个名为 Endpoint 的静态类来处理我的 API 调用。

      export class Endpoint {
      
          static lastStatus = '';
      
          static Get = (url, OKCallback, errorCallback = null) => {
              fetch(url)
                  .then(response => {
                      Endpoint.lastStatus = response.status;
                      return response.json();
                  })
                  .then(getResponse => {
                      if (Endpoint.lastStatus == 200) {
                          OKCallback(getResponse.body);
                      //} else if (Endpoint.lastStatus == 408) {
                      //    Special logic or callback for status code 408 goes here.
                      } else {
                          console.log("API Error: " + JSON.stringify(getResponse));
                          if (errorCallback != null) {
                              errorCallback(getResponse);
                          }
                      }
                  });
          }
      }
      

      如果您有想要单独处理的特定 HTTP 状态代码,例如 408,您可以在第二个“then”块中添加自己的逻辑或回调来处理它们。


      附:这种方法适用于我测试过的案例,但我不确定这是不是最好的方法。欢迎提供建设性反馈。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-09
        • 2017-02-07
        • 1970-01-01
        • 1970-01-01
        • 2016-07-13
        • 2018-02-05
        • 2019-02-02
        相关资源
        最近更新 更多