This scheme has two main functions

  • 1. After a request is sent, the subsequent repeated requests are cancelled and not processed until the first request is completed.
  • 2. After a route is redirected, all requests that are not completed on the previous page are cleared.

1. Cancel repeated requests

Pre-knowledge:

  • 1. The official cancellation method provided by AXIos can be referred to the relevant documentation: CancelToken
  • 2. Js Map related concepts
  • 3. Safe query string parsing and string decomposition library QS, functions similar to JS own JSON

In order to simplify parameter processing, this scheme only considers POST requests, that is, if method, URL and data are the same, they are regarded as repeated requests

// axios.js
const pending = new Map(a)/** * Add request *@param {Object} config* * /
const addPending = (config) = > {
  const url = [
    config.method,
    config.url,
    qs.stringify(config.data)
  ].join('&')
  if (pending.has(url)) { // Cancel subsequent requests if current requests exist in pending
    config.cancelToken = new axios.CancelToken(cancel= > cancel('Repeated requests are actively blocked:${url}`))}else { // If there is no current request in Pending, add it
    config.cancelToken = config.cancelToken || new axios.CancelToken(cancel= > {
      pending.set(url, cancel)
    })
  }
}
/** * Remove request *@param {Object} config* /
const removePending = (config) = > {
  const url = [
    config.method,
    config.url.replace(config.baseURL, ' '), // The response URL adds a domain name, which needs to be removed to be consistent with the request URL
    qs.stringify(JSON.parse(config.data)) // It needs to be consistent with the argument structure of request, which is an object in request and a string in response
  ].join('&')
  if (pending.has(url)) { // If the current request flag exists in pending, cancel the current request and remove it
    pending.delete(url)
  }
}

/* axios global request parameter setting, request interceptor */
axios.interceptors.request.use(
  config= > {
    addPending(config) // Add the current request to Pending
    return config
  },
  error= > {
    return Promise.reject(error)
  }
)
// Response interceptor is exception handling
axios.interceptors.response.use(
  response= > {
    removePending(response.config) // Remove the request after the request is complete
    return response
  },
  err= > {
    if (err && err.config) {
      removePending(err.config) // Remove the request after the request is complete
    }
    return Promise.resolve(err.response)
  }
)

Copy the code

Clean up all requests

// axios.js
/** * Clears requests in pending (called when a route jumps) */
export const clearPending = () = > {
  for (const [url, cancel] of pending) {
    cancel(url)
  }
  pending.clear()
}

Copy the code
// router.js
router.beforeEach((to, from, next) = > {
  // Route jump, clear all requests
  clearPending()
  })
Copy the code