Recommend a practical interview question bank to everyone
1. Front-end interview question bank (Essential for interviews) Recommended:
Address: Web front-end interview question bank
This question is very interesting. As soon as I saw it, I thought of a lot of answers to it, but the comment area was too narrow, so I just opened an article to write it.
Question review
Can requests initiated by JS be paused? There are two concepts that need to be clarified in this sentence. First, what kind of state can be called pause
? Second, what is the request initiated by JS
?
What constitutes a pause?
Pause
The full name is temporary stop. Temporary stop during the process that has been started but not ended can be called pause, which means that the process can be cut off at a certain point in time and then resumed at another point in time.
What should the request be?
Here we must first introduce the TCP/IP network model. The network model is divided into application layer, transport layer, network layer and network interface layer from top to bottom.
What the above picture means is that for every network transmission, application data needs to be packaged layer by layer through the network model before being sent to the target. Just like sending an express delivery, the items to be sent must be packed and registered first, and then Put it in the box and register the destination, then load it into the car and finally send it to the destination.
Request
This concept can be understood as the behavior of the client sending a single complete copy of data to the server through several data network transmissions, and the reply sent by the server to the client in response to a certain request The data can be called Response
.
In theory, the application layer protocol can implement the pause mechanism through a series of means such as marking packet sequence numbers. However, the TCP protocol does not support it. The data transmission of the TCP protocol is streaming, and the data is regarded as a series of byte streams. The data sent by the client will be split into multiple TCP segments, and these segments are transmitted independently in the network. The transmission of each TCP segment cannot be directly controlled, so it is impossible to pause the request or pause the response. Function.
Answer questions
If the request refers to a request transmission in the network model, then of course it is impossible to pause.
Let’s take a look at the usage scenario of the questioner – Request initiated by JS
, then it can be considered that the request in the question should refer to the XMLHttpRequest
initiated in the JS runtime or fetch
request, and since the request has been initiated, the natural question is whether the response can be suspended.
We all know that functions such as large file multi-part upload and multi-part download essentially require the fragments in order after setting the order. Then, we can interrupt the sequence and record the interruption point to realize the mechanism of pausing retransmission. A single request does not have such an environment.
Use JS to implement the “fake pause” mechanism
Although the pause request cannot be realized in a true sense, we can actually simulate a fake pause function. In the front-end business scenario, the data can be directly slapped on the customer’s face without being received (what’s the speed of light) (Blow), the front-end developer needs to process this data and then render it on the interface. If we can add a controller before the request is initiated, when the request comes back, if the controller is in a paused state, the data will not be processed and the controller will wait for recovery. Is it possible to achieve the goal by processing it later? Let’s try to implement it.
If we use fetch
to request. We can design a controller Promise
and put it together with the request and wrap it with Promise.all
. When fetch
is completed, the pause status of this controller will be determined. , if it is not suspended, the controller will also resolve directly, and the entire Promise.all
will also be resolved and thrown.
function _request () { return new Promise<number>((res) => setTimeout(() => { res(123) }, 3000)) } // Originally wanted to use class extends Promise to implement // As a result, this problem keeps appearing https://github.com/nodejs/node/issues/13678 function createPauseControllerPromise () { const result = { isPause: false, resolveWhenResume: false, resolve (value?: any) {}, pause () { this.isPause = true }, resume () { if (!this.isPause) return this.isPause = false if (this.resolveWhenResume) { this.resolve() } }, promise: Promise.resolve() } const promise = new Promise<void>((res) => { result.resolve = res }) result.promise = promise return result } function requestWithPauseControl <T extends () => Promise<any>>(request: T) { const controller = createPauseControllerPromise() const controlRequest = request().then((data) => { if (!controller.isPause) controller.resolve() controller.resolveWhenResume = controller.isPause return data }) const result = Promise.all([controlRequest, controller.promise]) .then(data => data[0]) result.finally(() => controller.resolve()) (result as any).pause = controller.pause.bind(controller); (result as any).resume = controller.resume.bind(controller); return result as ReturnType<T> & amp; { pause: () => void, resume: () => void } }
Usage
We can call requestWithPauseControl(_request)
instead of calling _request
, and control it through the returned pause
and resume
methods Pause and resume.
const result = requestWithPauseControl(_request).then((data) => { console.log(data) }) if (Math.random() > 0.5) { result.pause() } setTimeout(() => { result.resume() }, 4000)
Execution Principle
The process design is like this. Design a controller. After initiating a request and requesting return, the status of the controller is judged. If the controller is not in the “pause” state, the data will be returned normally; when the controller is in the “pause state”, the control The processor will be set to the state of “Return data once recovery method is called”.
The code uses Promise.all
to bundle a controller Promise
. If the controller is in a paused state, Promise.all
will not be released. Then expose the corresponding pause
method and resume
method to the outside world.
Supplement
Some students mistakenly believe that network requests and responses cannot be paused. I specifically mentioned the content about data transmission at the beginning of the article, and added: “Theoretically, the application layer protocol can be marked with packet sequence numbers, etc.” Wait for a series of means to implement the pause mechanism.” What this sentence means is that if you modify HTTP or design and implement an application layer protocol yourself (such as socket, vmess, etc.), as long as both ends support the protocol, it can be implemented. Request suspension or response suspension, and this will not affect the TCP connection, but implementing the suspension mechanism requires a thorough understanding of various scenarios and TCP policies to achieve better reliability.
For example, to provide a type of control message to control the transmission pause, you first need to mark the sequence of the sequence numbers of all data packets. When a pause is needed, a pause message with the sequence number is sent to the receiving end, and the receiving end receives the pause message. Just return the block mark of the received data packet to the sender and so on (this is the same as the multipart upload mechanism).
Finally
The above is all the content shared in this article.
This is Xekin (/zi:kin/). Friends who like it can like, follow and add it to favorites~
I have been spending a lot of time fishing recently, and I have written some strange and useful tools but not particularly useful, but they are still very interesting. I will write articles one by one to share them later. Thank you for your support.
Recommend a practical interview question bank to everyone
1. Front-end interview question bank (Essential for interviews) Recommended:
Address: Web front-end interview question bank