Axios:如何正确取消请求拦截器中的请求?

Tot*_*AMD 4 javascript axios

如果没有令牌,我想取消请求,所以我这样做:

instance.interceptors.request.use(config => {
  if (!getToken()) {
    console.log("interceptors: no access token");
  } else {
    config.headers.Authorization = "Bearer " + getToken().accessToken;
    return config;
  }
});
Run Code Online (Sandbox Code Playgroud)

但是在负面情况下,会出现错误TypeError: Cannot read property 'cancelToken' of undefined

Tho*_*dez 9

因此,无论出于何种原因,这些答案都不适合我。这是所做的。

axiosInstance.interceptors.request.use(
  function (config) {
    const controller = new AbortController();
    const cfg = {
      ...config,
      signal: controller.signal,
    };
    controller.abort('We gotta cancel this');
    return cfg;
  },
  function (error) {
    return Promise.reject(error);
  },
);
Run Code Online (Sandbox Code Playgroud)

我从中学到的东西:AbortController是 javascript/node 原生的。


gra*_*212 5

您不能在拦截器内部使用令牌,而是抛出 Cancel

axios.interceptors.response.use(function (response) {
  throw new axios.Cancel('Operation canceled by the user.');
}, function (error) {
  return Promise.reject(error);
});
Run Code Online (Sandbox Code Playgroud)

请参阅此帖子:https : //github.com/axios/axios/issues/583

  • OP要求在请求拦截器中提供解决方案 (4认同)
  • 它会导致 `function (error) {...}` 代码分支运行或仅在以后落入 `.catch()` 吗? (2认同)
  • 我猜你的意思是当你抛出 `axios.Cancel()` 时代码会流向哪里。我已经尝试过这个,取消将在稍后直接在 `catch()` 中显示为错误。 (2认同)

小智 5

我是这样实现的。我不确定这是否是最好的解决方案,但对于我的用例来说很有用。我的想法是不取消最后一个请求。我想取消先前对同一端点的请求,并让最后一个请求完成他的工作。因此,我会跟踪正在执行的请求。

// I keep track of the current requests that are being executed
const currentExecutingRequests = {};

axios.interceptors.request.use(
    (req) => {
        let originalRequest = req;

        if (currentExecutingRequests[req.url]) {
            const source = currentExecutingRequests[req.url];
            delete currentExecutingRequests[req.url];
            source.cancel();
        }

        const CancelToken = axios.CancelToken;
        const source = CancelToken.source();
        originalRequest.cancelToken = source.token;
        currentExecutingRequests[req.url] = source;

        // here you could add the authorization header to the request

        return originalRequest;
    },
    (err) => {
        return Promise.reject(err);
    }
);

axios.interceptors.response.use(
    (response) => {
        if (currentExecutingRequests[response.request.responseURL]) {
            // here you clean the request
            delete currentExecutingRequests[response.request.responseURL];
        }
        return response;
    },
    (error) => {
        const { config, response } = error;
        const originalRequest = config;

        if (axios.isCancel(error)) {
            // here you check if this is a cancelled request to drop it silently (without error)
            return new Promise(() => {});
        }

        if (currentExecutingRequests[originalRequest.url]) {
            // here you clean the request
            delete currentExecutingRequests[originalRequest.url];
        }

        // here you could check expired token and refresh it if necessary

        return Promise.reject(error);
    }
);
Run Code Online (Sandbox Code Playgroud)


Kir*_*ski 5

对于后来的 googlers,这是一个很好的解决方案,取自github 上axios 问题

instance.interceptors.request.use(config => {
  /* some logic */
  return {
    ...config,
    cancelToken: new CancelToken((cancel) => cancel('Cancel repeated request'))
  };
});
Run Code Online (Sandbox Code Playgroud)

这几乎是Vijay提出的,但形式更简洁。

  • 请注意,从 axios v0.22 开始,这是[已弃用](https://axios-http.com/docs/cancellation),并建议使用 `AbortController` (4认同)
  • 这个答案是正确的,但 CancelToken 已被弃用。请改用中止控制器,[使用更新后的答案中所示的 AbortSignal](/sf/answers/4996772511/) (2认同)