In the scenario encountered in the project, when fuzzy matching is triggered by the change event, multiple Ajax requests are sent within a short period of time. The last data returned may not be the last request triggered by the change event, resulting in data mismatch

The solution

The use ofAxiosTo make data requests, usecancel tokenCancel the request

Official case github.com/axios/axios


    // using the CancelToken.source factory 
    const CancelToken = axios.CancelToken 
    const source = CancelToken.source()
    
    // get
    axios.get('/user/1', {
        cancelToken: source.token
    }).catch(function (thrown) {
        if(axios.isCancel(thrown)) {
            console.log('Request canceled', thrown.message)
        } else {
            // handle error}})// post
    axios.post('/user/1', {
        name: ' '
    }, {
        cancelToken: source.token
    })
    
    // Cancel Request parameter Optional
    source.cancel('Cancel last request')

Copy the code

    // use executor function
    const CancelToken = axios.CancelToken
    let cancel
    
    // get
    axios.get('/user/1', {
        cancelToken: new CancelToken(function executor(c) {
            // The executor function takes a cancel function as an argument
            cancel = c
        })
    })
    
    // post
    axios.post('/user/1', {
        name: ' '
    }, {
        cancelToken: new CancelToken(function executor(c) {
            cancel = c
        })
    })
    
    // cancel request
    cancel()

Copy the code

Example of my Vue project

    import axios from 'axios'
    let cancel
    let CancelToken
    
    mounted() {
        CancelToken = axios.CancelToken
    }
    
    FetchList cancels the last request and triggers the latest one
    async fetchList() {
        if(cancel) {
            cancel()
        }
        await axios.post('/user/list', {
            query: ' '
        }, {
            cancelToken: new CancelToken(function executor(c) {
                cancel = c
            })
        })
    }

Copy the code

Native XHR

The native XHR object calls abort() to cancel the Ajax request

    
    let xhr
    if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest()
    } else {
      xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    xhr= new XMLHttpRequest()
    xhr.open('GET'.'https://api')
    xhr.send()
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        // success
      } else {
        // error}}// Cancel the Ajax request readyState = 0
    xhr.abort()

Copy the code

AxiosSource light parsingCancelToken

axios/lib/cancel/CancelToken.js


    'use strict';

    var Cancel = require('./Cancel');
    
    function CancelToken(executor) {
        if (typeofexecutor ! = ='function') {
            throw new TypeError('executor must be a function.');
        }
        /** * Assign the promise's resolve method to a resolvePromise in order to use the resolvePromise method outside of the promise object to change the state of the object * /
        var resolvePromise;
        this.promise = new Promise(function promiseExecutor(resolve) {
            resolvePromise = resolve;
        });
        /** * Assign the CancelToken instance to token * pass the Cancel method to executor, which calls the resolvePromise method */
        var token = this;
        executor(function cancel(message) {
            if (token.reason) {
                // Cancel the response returned
                return;
            }
            token.reason = new Cancel(message);
            // Execute the promise's resolve method to change the state
            resolvePromise(token.reason);
      });
    }
    
    CancelToken.prototype.throwIfRequested = function throwIfRequested() {
        if (this.reason) {
            throw this.reason; }}; CancelToken.source =function source() {
        var cancel;
        var token = new CancelToken(function executor(c) {
            // c is the cancel method passed to executor in CancelToken
            cancel = c;
        });
        return {
            token: token,
            cancel: cancel
        };
    };
    
    module.exports = CancelToken;

Copy the code

How do I cancel the Ajax request after promise.resolve()

  1. willCancelTokenAdded to theaxiosCancelTokenOn the properties
    // axios/lib/axios.js
    
    axios.Cancel = require('./cancel/Cancel');
    axios.CancelToken = require('./cancel/CancelToken');
    axios.isCancel = require('./cancel/isCancel');
Copy the code
  1. CancelTokenresolveMethod triggerpromise.thenmethods
    // axios/lib/adapters/xhr.js
    
    // Create an XHR object
    var request = new XMLHttpRequest()
    // Simulate the current Ajax request
    request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true)
    
    if (config.cancelToken) {
        config.cancelToken.promise.then(function onCanceled(cancel) {
            if(! request) {return;
            }
            // Cancel the Ajax request
            request.abort();
            reject(cancel);
            // Clean up request
            request = null;
        });
    }
    
Copy the code