Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Axios:如何在请求拦截器中正确取消请求?_Javascript_Axios - Fatal编程技术网

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

Javascript Axios:如何在请求拦截器中正确取消请求?,javascript,axios,Javascript,Axios,如果没有令牌,我想取消请求,因此我喜欢这样做: instance.interceptors.request.use(配置=>{ 如果(!getToken()){ log(“拦截器:无访问令牌”); }否则{ config.headers.Authorization=“Bearer”+getToken().accessToken; 返回配置; } }); 但是在负面场景中会出现一个错误TypeError:无法读取未定义的属性“cancelToken”您不能在拦截器内使用该令牌,而是抛出Cance

如果没有令牌,我想取消请求,因此我喜欢这样做:

instance.interceptors.request.use(配置=>{
如果(!getToken()){
log(“拦截器:无访问令牌”);
}否则{
config.headers.Authorization=“Bearer”+getToken().accessToken;
返回配置;
}
});

但是在负面场景中会出现一个错误
TypeError:无法读取未定义的属性“cancelToken”
您不能在拦截器内使用该令牌,而是抛出
Cancel

axios.interceptors.response.use(function (response) {
  throw new axios.Cancel('Operation canceled by the user.');
}, function (error) {
  return Promise.reject(error);
});
请参阅本帖: 以下是解决方案

import axios from 'axios';

const CancelToken = axios.CancelToken;
let cancel;

axios.interceptors.request.use((config) => {

  if (cancel) {
    cancel(); // cancel request
  }

  config.cancelToken =  new CancelToken(function executor(c)
    {
      cancel = c;
    })

  return config

}, function (error) {
  return Promise.reject(error)
});


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

// 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);
    }
);
我的解决方案基于

axios.ts

const axiosInstance = axios.create({ baseURL: apiBaseUrl });

axiosInstance.interceptors.request.use(
    req => {
        const originalRequest = req;
        const cancelUniqId = (originalRequest.cancelToken as unknown) as string;

        if (Object.hasOwnProperty.call(currentExecutingRequests, cancelUniqId)) {
            const source = currentExecutingRequests[cancelUniqId];
            delete currentExecutingRequests[cancelUniqId];
            source.cancel();
        }

        if (cancelUniqId) {
            const CancelToken = axios.CancelToken;
            const source = CancelToken.source();
            originalRequest.cancelToken = source.token;
            currentExecutingRequests[cancelUniqId] = source;
        }

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

axiosInstance.interceptors.response.use(
    response => {
        for (const key of Object.keys(currentExecutingRequests)) {
            if (currentExecutingRequests[key].token === response.config.cancelToken) {
                delete currentExecutingRequests[key];
                break;
            }
        }
        return response;
    },
    error => {
        const { response } = error;

        if (axios.isCancel(error)) {
            return new Promise(() => {
                //
            });
        }

        for (const key of Object.keys(currentExecutingRequests)) {
            if (currentExecutingRequests[key].token === response.config.cancelToken) {
                delete currentExecutingRequests[key];
                break;
            }
        }

        return Promise.reject(error);
    }
);

export { axiosInstance };
用法:

axiosInstance.request({
    url: "some/req/path",
    method: "POST",
    params: {...},
    data: {...},
    cancelToken: "someUniqRequestID" // <-- IMPORTANT!
})
axiostation.request({
url:“some/req/path”,
方法:“张贴”,
参数:{…},
数据:{…},

cancelToken:“someUniqRequestID”//对于后来的谷歌来说,这是一个从

这与提议的内容基本相同,但形式更为简洁。

@的回答完美地解决了这一问题,但添加了一行:

const CancelToken=Axios.CancelToken;
然后,事情会是这样的:

instance.interceptors.request.use(配置=>{
/*一些逻辑*/
const CancelToken=Axios.CancelToken;
返回{
…配置,
cancelToken:new cancelToken((cancel)=>cancel('cancel repeated request'))
};
});

它是否会导致
函数(错误){…}
代码分支运行或仅在稍后落入
.catch()
中?我猜您的意思是,当您抛出
axios.Cancel()
时,代码将流向何处。我已经尝试过这一点,取消将在
catch()中显示为错误
稍后直接执行。这在编写时是不正确的(您不能在拦截器中使用cancel令牌),并且不能处理所有用例,例如,如果请求已经启动,您现在需要取消所有请求(例如,由于会话到期,用户已注销)。关于这一点,请参阅vijay的解决方案。OP要求在请求截获中提供解决方案。我认为这是关于取消已运行的请求,OP谈论的是一个尚未启动的请求。什么是
“让取消”
?以及为什么您要检查它是否正确,然后再调用它!我很困惑。您还可以演示如何在useffect中清理已取消的请求吗你的意思是这样的吗?
React.useffect(()=>{const CancelToken=axios.CancelToken;const source=CancelToken.source();(async()=>{try{const response=wait axios.get(URL,{CancelToken:source.token});console.log(response);}catch(e){console.log(e);}}}();return()=>source.cancel();},[]);
您可以在这里查看它以了解更多说明:
instance.interceptors.request.use(config => {
  /* some logic */
  return {
    ...config,
    cancelToken: new CancelToken((cancel) => cancel('Cancel repeated request'))
  };
});