Search code examples
vue.jsaxiosvuexcancellation

How to cancel all unneccesary requests in vuex, axios


I have a situation: when I live a page, async functions in mounted hook continue working (such as await this.getUser({id: 1})). I'm trying to use axios.CancelToken, but unfortunately it cancels only the first request (not all requested). Send request function:

const source = axios.CancelToken.source();
const config = {
    headers: {
        authorization: `${prefix}${localStorage.getItem('authorization')}`
    },
    cancelToken: source.token
};
store.commit('SET_CANCEL_SOURCE', source);

const response = await axios.get(url, config);

Store mutations:

SET_CANCEL_SOURCE: (state, cancel: CancelTokenSource) => {
    state.cancelTokens.push(cancel);
},
RESET_CANCEL_TOKENS: (state) => {
    if (state.cancelTokens.length) {
        state.cancelTokens.map((item: any, index: number) => {
            console.log(index, item);
            item.cancel();
        });
        state.cancelTokens = [];
    }
}

Store action:

clearToken ({commit}) {
    commit('RESET_CANCEL_TOKENS');
}

And beforeUnmount for component:

beforeUnmount() {
    this.clearToken();
}

Any ideas?


Solution

  • The point is that CancelToken cancels only those requests that are already sent. The best solution I found is to make stages of loading information, create a variable, that represents the current stage and in beforeUnmount make variable isCancelled = true. So that next stages will not be excuted. Example:

    data: () => ({
        stage: 0,
        isCancelled: false,
    }),
    async setInitialData() {
        if (this.stage >= 4 || this.isCancelled) {
            return;
        }
    
        switch (this.stage) {
            case 0:
                await action1();
                break;
    
            case 1:
                await action2();
                break;
    
            case 2:
                await action3();
                break;
    
            case 3:
                await action2();
                break;
    
            default:
                break;
        }
    
        this.stage++;
        await this.setInitialData();
    },
    async mounted() {
        await this.setInitialData();
    },
    beforeUnmount() {
        this.isCancelled = true;
    },