Can requests initiated by JS in the front end be paused?

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.

image.png

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.

image.png

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