首页 > 解决方案 > 在axios中检测xhr.status === 0

问题描述

语境

我有一个在公司环境中运行的网络应用程序,所有请求都通过我无法控制的代理。该层会根据需要自动将我的用户重定向到不同域上的单点登录页面。

这是基本顺序:

  1. 用户myapp.example.corp在浏览器中输入
  2. 请求通过代理,它检查用户是否登录
  3. 用户未登录,因此他们被重定向到登录auth.example.corp
  4. 用户登录,然后被重定向到我的应用

到现在为止还挺好。

问题

我想问的问题出现在以下场景中:

  1. 用户在我的应用程序中做了一些工作,然后回家,让浏览器选项卡保持打开状态
  2. 一些时间过去了,用户的会话过期了
  3. 用户在我的应用打开并继续使用它的情况下返回浏览器选项卡
  4. 我的应用发出 AJAX 请求,它们通过同一个代理
  5. 由于用户不再登录,这些请求被重定向到登录页面
  6. 由于该登录页面位于不同的域中,因此将以下内容记录到浏览器控制台,这对于了解正在发生的事情非常有用
Failed to load https://auth.example.corp: No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin 'https://myapp.example.corp'
is therefore not allowed access.

(这个问题与 CORS 无关。我无法控制代理或身份验证服务器。请不要分心。)

真正的问题是,在我使用 axios 的应用程序代码中,我传递给 axios 的回调永远不会被调用。此请求的承诺永远不会得到解决或拒绝。在我的代码中我无法检测到任何事情。

// none of these callbacks get called
axios
  .get("/signedin")
  .then(response => console.log("Signed in"))
  .catch(response => console.log("Not signed in"))

一种解决方法

如果我改为使用XMLHttpRequestAPI,我可以检测到这种情况,因为触发了一个onreadystatechange事件并且我可以测试request.status === 0.

var request = new XMLHttpRequest();
request.onreadystatechange = event => {
  if (request.readyState === 4 && request.status === 0) {
    console.log("Not signed in");
  }
};
request.open("GET", "/signedin");
request.send();

问题

所以我的问题是:我真的很想继续使用 axios 但能够检测到这种情况。在使用 axios 时是否有某种检测xhr.status == 0方法或者我是否被迫使用XMLHttpRequest

标签: javascriptxmlhttprequestaxios

解决方案


CORS 是问题所在,每当预检请求失败时,浏览器将完全拒绝访问返回状态代码、响应正文和标头等内容。这就是 axios 永远不会知道这一点的原因,这可能是 promise 没有关闭的原因它有点相似到没有任何超时限制的网络故障。但是你可以尝试像这样的拦截器来检测这种情况

axios.interceptors.response.use((response) => response, (error) => {
  if (typeof error.response === 'undefined') {
      //alert the failure
  }
  return Promise.reject(error);
});

推荐阅读