This article has participated in the activity of “New person creation Ceremony”, and started the road of digging gold creation together

preface

The most important thing about canceling repeated requests is the meaning of doing so, not the implementation of the code

In fact, I think, the vast majority of application scenarios, can think of can all be done through stabilization, throttling, such as real-time search, such as in the repeat orders, such as “for the latest data, and so on We know that the so-called request, is the request has been issued, just cancelled in a timely manner, the entire request process has not completed, It is possible to simply send the request to the server and cancel it before receiving the result from the server, which is simply not processing the result from the server

Of course, the benefits of doing so are obvious, such as the pull-up load data, in the whole pull-up process, may be frequent requests, each request returned, the data will be rendered to the page, frequent operations will cause problems such as page jitter. If you cancel the duplicate request, you can avoid this problem by simply making the request and not processing the previous result returned by the server, but only the last result returned

Here is a simple talk, more hope that some students can system to cancel the repeated request, from the front and back end of the coordination of the point of view to the system to talk about, I even throw a brick to attract jade

1. The request always arrives at the server

This section, just to prove a point: cancel the request, the request will also reach the server!

It makes sense to consider how to prevent the problems caused by duplicate submissions

1.1 XMLHtppRequest

Let’s start with the most basic XMLHtppRequest object to illustrate this

1. The server code accepts a GET request and returns data

const express = require('express') const cors = require('cors') const app = express() app.use(cors()) app.get('/users', (req, res, next) => {const obj={name:'yhb', age:20} console.log(' request reached ') res.send(obj)})Copy the code

2. Client code

After you click the button, send the Ajax request, and then cancel the repeat request

document.querySelector('button').addEventListener('click', () = > {const XHR = new XMLHttpRequest () const url = 'http://127.0.0.1:3000/users' XHR. Open (" get ", Url) xhr.onReadyStatechange = () => {console.log(xhr.readystate)} xhr.send() // Cancel repeated requests using the about method setTimeout(() => { xhr.abort() }, 1000) })Copy the code

3, test,

Under normal network conditions, it doesn’t make sense to cancel the request because the network speed is fast enough and the server doesn’t set latency, so you can’t click the button as fast as the network

We can change the browser’s network to “low speed 3G” and click the button again to find that the request has been canceled

Look at the server side

As you can see, even though the request has been canceled, the request still reaches the server

Therefore, from this point of view, it is absolutely not feasible for services such as order submission to avoid the generation of multiple orders only by canceling repeated requests, and the server must conduct idempotent judgment and other methods to prevent the generation of repeated orders

4, the conclusion

So what does canceling repeated requests, the About method, actually do?

Here is a description of the about method on MDN

As you can see, the About method does not, and does not, prevent the request from being sent; it simply does not accept the data returned by the server

Let’s look at the output by looking at different networks

Normal network

Low speed for 3 g

The output is only 4

We can see that by comparing the readyState property value

If readyState, if it just prints a 4, it means that the entire network request, instead of going through the two stages of getting the header information and the status information from the server and downloading the data from the server, just thinks that the request is complete, so we don’t see anything in the network

1.2 Axios cancels duplicate requests

Axios is a very popular library for web requests that, if applied to a web page, internally calls an XMLHttpRequest object (I haven’t checked to see if this is the case in the latest version), so cancel the request and still call the About method

Below is the code, the specific code meaning, will be introduced in detail later, here as long as understand, the execution result is exactly the same as above

document.querySelector('button').addEventListener('click', () => { const CancelToken = axios.CancelToken; Let the cancel axios. Get (' http://127.0.0.1:3000/users' {cancelToken: new CancelToken(function executor(c) { cancel = c }) }).then(res => { console.log(res.data) }).catch(err => { console.log(err) }) setTimeout(() => { cancel('Operation canceled by the user.'); // Cancel request with optional}, 1000)})Copy the code

1.3 the conclusion

The above code test verifies our conclusion

  • The so-called cancel request is only the operation after the request has been sent and has reached the server, and does not prevent the request from being sent
  • Whether or not the request is canceled, the server has received the request information, including the parameter information sent with the request
  • When the client cancels the request, it simply cancels the step of receiving the message back from the server

Is this conclusion necessarily correct? Who knows!

Everyone put forward their own opinion!

2. Cancel repeated requests

In conjunction with the real-time search scenario, this section explains how to avoid some of the problems by canceling repeated requests

The first thing to understand is that canceling a duplicate request is not effective in a good network condition, or if the back end is responding quickly, because by the time you want to cancel the last request, the entire network request will have been completed

Therefore, our following case, is in “low speed 3G” this kind of network condition is not good operation, simulation is the network delay, the server response is slow this kind of case, how to cancel the repeated request, achieve the purpose of the page does not jitter

2.1 Server code

Returns search suggestions based on user input

const express = require('express') const cors = require('cors') const app = express() app.use(cors()) app.get('/search', (the req, res, next) = > {const data = [{key: "spring", result: [' spring ', 'spring']}, {key: "spring", the result: [' spring breeze gifts', 'anyone']}, {key: 'in the spring, the result: [' wind of spring', 'spring scenery']}, {key: 'the wind of spring, the result: [' The spring wind is intoxicating ', }] const key = req.query.key // Filter const filter_data = data.filter(item => {return item.key === key}) if (filter_data.length === 0) { return res.send([]) } console.log(filter_data[0].key) res.send(filter_data[0].result || []) }) app.listen(3000, () => {console.log('server is runnig at http://127.0.0.1:3000')})Copy the code

2.2 Client code

<template> <div id="app"> <div> <input type="text" v-model="key" @keyup="getSuggest" /> </div> <div class="result"> <div  v-for="(item, index) in suggestList" :key="index"> {{ item }} </div> </div> </div> </template> <script> import axios from "./api/axios"; // import axios from "axios"; export default { name: "App", data() { return { key: "", suggestList: [], }; {}, the methods: {getSuggest () const res = axios. Get (` http://127.0.0.1:3000/search `, {params: {key: this key,},}); res .then((response) => { console.log(response.data); this.suggestList = response.data; }) .catch((err) => { console.log("11"); }); ,}}}; </script> <style> </style>Copy the code

2.3 test

Under normal network conditions:

  • As the key event of the text box occurs, requests continue to be sent, and all requests are successful
  • There is no problem with the search suggestions displayed below the text box

Low speed for 3 g

  • As the key event of the text box occurs, requests continue to be sent, and all requests are successful
  • The search suggestions below the text box display a strange phenomenon: the list of search suggestions is not displayed during typing, but the list magically changes after the search has ended for a while
  • The search suggestion list cannot be updated in a timely manner due to network problems. However, after a period of time, many responses from the server are returned almost at the same time. As a result, the search suggestion list is frequently updated, causing the display of the search suggestion to jitter
  • Because the network is slow, please watch the GIF patiently

Conclusion:

  • In both cases, a large number of requests are sent as the text box is entered
  • In low-speed 3G networks, the response of requests is not timely, but it is very likely that many requests will be very dense

Now let’s look at how to cancel duplicate network requests in AXIos

2.4 Axios cancels duplicate requests

2.4.1 How to Identify Repeated Network Requests

How do you identify repeated requests?

A request is considered the same when the request style, request URL, and request parameters are the same

This can be done every time a request is made

  1. Generates a unique key based on the request type, request URL, and request parameters of the current request
  2. Create an exclusive CancelToken for each request.
  3. Store the key and cancel functions as key-value pairs
  4. When a duplicate request occurs, cancel the previous request using the cancel function
  5. Removes the cancelled request from the collection

Here are the steps

2.4.2 Creating Several Functions

The following three functions are used for

  • Generate a key based on the request information
  • Stores the generated key and the corresponding Cancel function generated object into the map
  • Deletes a network request object from the map

1. Define functions to generate keys based on the request

Const generateKey = (config) => {let {method, url, params, data} = config; return [method, url].join("&"); }Copy the code

As mentioned above, the criteria for repeating requests are: the request address, request mode, and request parameters are consistent

So, in the code above, we structure the parameters in the request address, request mode, request header, and request body from the Config object

However, when the key is generated, the two parameters are not involved. The reason is that in the real-time search scenario, the parameters must be different each time. If the parameters are also involved in the key generation, the repeated request cannot be constructed

Be flexible

Add the request object to the map

**/ let pendingRequest = new Map(); Function addPendingRequest(config) {const requestKey = generateKey(config); /** * add a cancelToken for this request. * at the same time will be the key and cancel the function of objects are added to the map * / config. CancelToken = config. CancelToken | | new axios. CancelToken (= > {if ((cancel)! pendingRequest.has(requestKey)) { pendingRequest.set(requestKey, cancel); }}); }Copy the code

3. Delete the request object from the map

**/ function pendingRequest (config) {let requestKey = generateKey(config); Pendingrequest.has (requestKey)) {if (pendingRequest.has(requestKey)) {if (pendingRequest.has(requestKey)) {if (pendingRequest.has(requestKey)) {let cancel = pendingRequest.get(requestKey); // This line of code cancels the request cancel(requestKey); Pendingrequest.delete (requestKey); // Remove the previous repeated request. }}Copy the code

2.4.3 Application in interceptors

When any request is made, the removePendingRequest function is first executed in the request interceptor. This function determines whether the request is a duplicate and, if so, cancels the request and removes the last I request information from the map

The addPendingRequest method is then called to add the cancel request function to the configuration of the request and add the request to the map

When any response is returned, whether it is successful or unsuccessful, it indicates that the request has been successfully completed and the request has ended. The removePendingRequest function will be called to remove the request information from the map. Otherwise, the next time the request is sent, the request will be considered to have been sent and the request will be deleted. It’s a request that has already been completed and doesn’t make any sense

1. Call a function in a request interceptor

/ * * * @ description request interceptor * * / axios. Interceptors. Request. Use (function (config) {/ / check whether there is a repeated request, if any cancel already sent the request, Cancel removePendingRequest (config); // Add the current request information to the pendingRequest object, addPendingRequest(config); return config; }, function (error) { return Promise.reject(error); });Copy the code

2. Delete duplicate requests from corresponding interceptors

/ response interceptor * * * * * @ the description/axios interceptors. Response. Use (function (response) {/ / the response data removePendingRequest(response.config); return response; }, function (error) {/ / removed from the pendingRequest object request removePendingRequest (error. The config | | {}); If (axios.iscancel (error)) {console.log(" repeated request cancelled: "+ error.message); } return Promise.reject(error); });Copy the code

The code in AXIos is not explained in detail above, because it is a routine thing that can be understood by looking at the documentation and debugging, so you can observe it more carefully

2.4.4 test

Running the code on a normal network has the same effect as setting up a repeat request, because when you want to cancel the last request, it has already been completed and cannot be cancelled at all

But on low-speed 3G networks, in frequent requests, the previous request is cancelled and only the last request is successful

Looking again at the console output, combined with the client code above, you can conclude

Through the way of eliminating duplicate request, though unable to control the number of times the network request, but, after the cancellation request, there is no response, will not perform then method in the client code of the above, it won’t be back for the variable suggestList assignment, nature also won’t perform a search suggestion list apply colours to a drawing, nature is no jitter

It’s only the last request that didn’t get canceled, and then comes in, and everything else is the catch that gets executed, because canceling the request throws an exception that we caught

3. Summary

① Canceling repeated requests is useful, but only in certain conditions, such as network congestion or slow server response

② Once the request is cancelled, the then method will not be executed, but the code in the catch method will be executed

(3) the above network card, and so on and so forth, after all, not every day, under normal circumstances, cancel the repeat request can not meet the second said, because you cancel request response speed faster than the speed, so even with the cancel the repeat request code, but when the content of the text box changes, there are still very frequent network request, As a result, dom updates are very frequent, so anti-shaking or throttling is necessary to reduce requests and DOM updates

(4) Even if the request is canceled, the request is sent to the server