在 React JS 中使用 fetch 处理响应状态

Posted

技术标签:

【中文标题】在 React JS 中使用 fetch 处理响应状态【英文标题】:Handling response status using fetch in react JS 【发布时间】: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 那么响应就不行了 tjvantoll.com/2015/09/13/fetch-and-errors 【参考方案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”块中添加自己的逻辑或回调来处理它们。


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

【讨论】:

以上是关于在 React JS 中使用 fetch 处理响应状态的主要内容,如果未能解决你的问题,请参考以下文章

React JS Fetch 返回空响应,但 Postman 没有

使用React Native Fetch中的对象响应时未处理的Promise Rejection

React Native网络编程之Fetch

在序列中调用 React js Fetch 调用

React.js:使用 Fetch API 和对象数组中的道具加载 JSON 数据

使用 redux-saga 和 fetch 自动处理 401 响应