在获取期间无法在 try-catch 中捕获 403

Posted

技术标签:

【中文标题】在获取期间无法在 try-catch 中捕获 403【英文标题】:Unable to catch 403 in try-catch during fetch 【发布时间】:2019-02-26 17:25:47 【问题描述】:

我正在使用 ReactJS 发出 put 请求,但是,当我输入错误的电子邮件/密码组合时,我会在 Chrome 上登录,即使我试图捕获所有错误并将它们显示在 errorDiv

async connect(event) 
  try 
    const userObject = 
      username: this.state.userName,
      password: this.state.password
    ;
    if (!userObject.username || !userObject.password) 
      throw Error('The username/password is empty.');
    
    let response = await fetch(('someurl.com'), 
      method: "PUT",
      headers: 
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      ,
      body: JSON.stringify(userObject)
    );
    let resJSON = await response.json();
    if (!response.ok) 
      throw Error(resJSON.message);
    
    console.info(resJSON.message);
    console.info(resJSON.message.auth_token);
    window.location = "/ledger/home";
   catch (e) 
    document.getElementById("errorDiv").style.display = 'block';
    document.getElementById("errorDiv").innerhtml = e;
  

【问题讨论】:

代码没问题。问题无法复制,stackblitz.com/edit/react-pb51rz 【参考方案1】:

根据mdn,fetch 只会在遇到网络错误时抛出。404(或403)不是网络错误。

即使响应是 HTTP 404 或 500,从 fetch() 返回的 Promise 也不会拒绝 HTTP 错误状态。相反,它会正常解析(将 ok 状态设置为 false),并且只会拒绝网络故障或是否有任何事情阻止请求完成。

例如,404 不构成网络错误。对成功 fetch() 的准确检查包括检查 promise 是否已解决,然后检查 Response.ok 属性的值是否为 true

【讨论】:

所以我无法捕捉到它并将其显示给用户,而不是自动创建日志?【参考方案2】:

我完全同意@Sagiv,但是有一个快速的解决方法可以做到这一点,尽管这不是建议的方法。 在 try 或 promise.then() 中,你需要做这个检查。

const res = await fetch();
console.log(res);    // You can see the response status here by doing res.status

因此,通过一些简单的检查,可以解决或拒绝一个承诺。例如在你的情况下

async connect(event) 
  try 
    const userObject = 
      username: this.state.userName,
      password: this.state.password
    ;
    if (!userObject.username || !userObject.password) 
      throw Error('The username/password is empty.');
    
    let response = await fetch('someurl.com', 
      method: 'PUT',
      headers: 
        Accept: 'application/json',
        'Content-Type': 'application/json'
      ,
      body: JSON.stringify(userObject)
    );
    if (response.status === 403) throw new Error('403 is unacceptable for me!');
    let resJSON = await response.json();
    if (!response.ok) 
      throw Error(resJSON.message);
    
    console.info(resJSON.message);
    console.info(resJSON.message.auth_token);
    window.location = '/ledger/home';
   catch (e) 
    document.getElementById('errorDiv').style.display = 'block';
    document.getElementById('errorDiv').innerHTML = e;
  

我强烈建议使用axios。 fetch问题可以参考这个link

【讨论】:

【参考方案3】:

这是因为您抛出错误,然后捕获部分代码未执行。试试这个:

async connect(event) 
  try 
    const userObject = 
      username: this.state.userName,
      password: this.state.password
    ;
    if (!userObject.username || !userObject.password) 
      throw Error('The username/password is empty.');
    
    let response = await fetch(('someurl.com'), 
      method: "PUT",
      headers: 
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      ,
      body: JSON.stringify(userObject)
    ).then(response => 
       response.json();
       console.info(resJSON.message);
       console.info(resJSON.message.auth_token);
       window.location = "/ledger/home";
    ).catch(e => 
    document.getElementById("errorDiv").style.display = 'block';
    document.getElementById("errorDiv").innerHTML = e;
  )

【讨论】:

我是否在最后一行之后添加另一个捕获?由于 .catch 在 try 本身内。

以上是关于在获取期间无法在 try-catch 中捕获 403的主要内容,如果未能解决你的问题,请参考以下文章

try-catch默认捕获所有异常

Try-Catch无法正确定位异常位置,我推荐2个有效技巧

iOS:在相机预览期间捕获图像而不采取行动

C#中关于try-catch的异常捕获问题

C#中关于try-catch的异常捕获问题

C# 无法避免嵌套的 try-catch