在 axios 中检测 xhr.status === 0

Chr*_*alo 2 javascript xmlhttprequest axios

语境

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

这是基本顺序:

  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.
Run Code Online (Sandbox Code Playgroud)

(这个问题与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"))
Run Code Online (Sandbox Code Playgroud)

解决方法

如果我改用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();
Run Code Online (Sandbox Code Playgroud)

问题

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

Vin*_*ney 5

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

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