This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

preface

The last article wrote a vue2 source code analysis of nextTick response is not good, so I wrote half of the second vue source code analysis into this article, hoping to have a little more interaction.🤕

The following guarantees are typed out by my own hand, so they guarantee originality, but not correctness.

concept

Flow limiting scheduler, the original intention is to limit the flow of JS tasks (do not do more than one at the same time), in my understanding of THE JS task flow limiting is actually mainly to limit the FLOW of HTTP requests of JS, because other tasks need to limit the flow of the scene I have not encountered (this scene is certain, there are welcome to interact with me ~~). Why do YOU need to limit HTTP requests? This is because there are restrictions on HTTP requests in various environments

  1. Network speed is limited (the network is not that fast)
  2. Server response speed is limited (the server is not that fast)
  3. The browser tohttpRequests are limited
    1. The number of simultaneous requests is limited
    2. The number of requests waiting in the queue is limited

Here is a small example to verify point 3

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      for (let i = 0; i < 2000; i++) {
        fetch(` http://127.0.0.1:3000/get? index=${i}`)}</script>
  </body>
</html>
Copy the code
const express = require('express')
const app = express()
const sleep = async (time) => {
  return new Promise((res) = > {
    setTimeout(res, time)
  })
}
app.get('/get'.async (req, res) => {
  await sleep(10000)
  res.end(' ')
})
app.listen(3000.() = > {
  console.log('Turned on')})Copy the code

The second scenario (sending a large number of requests at the same time, over a thousand) rarely happens, so the first scenario (the browser only sending six requests at the same time) requires limiting the flow of less important requests (such as preloading a hundred images) to prevent blocking important ones (such as user check-ins).

implementation

Train of thought

  1. There must be a cache to store requests that have not yet been sent
  2. There must be an upper limit, which must be less than 6, and when the number of requests being made is greater than that, no more requests will be made

code

There is no handling of boundary cases and no handling of error reports, just simple code implementation

class LimitRequest {
  // Limit the number of simultaneous requests
  limitCount = 0
  // Cache requests that have not yet been sent
  cacheRequest = []
  // The number of requests currently being made
  currentRequest = 0
  constructor(limitCount) {
    this.limitCount = limitCount
  }
  /** * New request *@param {*} fn* /
  addRequest(fn) {
    // Cache this request
    this.cacheRequest.push(fn)
    // Send the request
    // The send request can be called manually by the user without writing it
    this.request()
  }
  /** * take a request from the cache and send */
  async request() {
    if (this.currentRequest >= this.limitCount) {
      // If the current number of requests exceeds the limit, no new requests are sent
      return
    }
    // Add one to the number of requests currently being made
    this.currentRequest++
    // Retrieve the cached request
    const fn = this.cacheRequest.shift()
    // Send the request
    await fn()
    // The request is completed. The number of requests currently being sent is reduced by one
    this.currentRequest--
    // You can make a request again
    this.request()
  }
}
Copy the code

The complete code

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class LimitRequest {
        // Limit the number of simultaneous requests
        limitCount = 0
        // Cache requests that have not yet been sent
        cacheRequest = []
        // The number of requests currently being made
        currentRequest = 0
        constructor(limitCount) {
          this.limitCount = +limitCount || 3
        }
        /** * New request *@param {*} fn* /
        addRequest(fn) {
          if (typeoffn ! = ='function') {
            console.log('addRequest adds request requires passing function ')
            return
          }
          // Cache this request
          this.cacheRequest.push(fn)
          // modify, here not to call, leave the user at the appropriate time to call
        }
        /** * take a request from the cache and send */
        async request() {
          if (this.currentRequest >= this.limitCount) {
            // If the current number of requests exceeds the limit, no new requests are sent
            return
          }
          // Add one to the number of requests currently being made
          this.currentRequest++
          // This is a request to the upper limit
          this.request()
          try {
            // Retrieve the cached request
            const fn = this.cacheRequest.shift()
            // Send the request
            await fn()
          } catch (err) {
            console.log('Fn execution error', err)
          } finally {
            // The request is completed. The number of requests currently being sent is reduced by one
            this.currentRequest--
            if (this.cacheRequest.length) {
              // A quota is available, and there is a request, you can request again
              this.request()
            }
          }
        }
      }
      const limitRequest = new LimitRequest(3)
      for (let i = 0; i < 2000; i++) {
        limitRequest.addRequest(async() = > {await fetch(` http://127.0.0.1:3000/get? index=${i}`)})}setTimeout(() = > {
        // After 3 seconds, the browser is free and the request is sent
        limitRequest.request()
      }, 3000)
    </script>
  </body>
</html>
Copy the code

The last

Welcome to add my wechat ~~~~