阅读 135

代码片段之js限流调度器

以下保证都是我自己手敲出来的, 所以保证了原创性, 保证不了正确性.

概念

限流调度器, 本意是指对 js 的任务进行限流(同时不要做多个), 在我理解 js 中对任务限流其实主要就是对jshttp请求进行限流, 因为其他任务需要限流的场景我还没有遇到过(这种场景是肯定有的, 有遇到的欢迎和我互动啊~~). 为什么需要对http请求进行限流呢? 因为各种环境对http请求都有限制

  1. 网络速度有限制(网络没有那么快)

  2. 服务器响应的速度有限制(服务器没有那么快)

  3. 浏览器对http请求有限制

    1. 同时请求数量有限制

    2. 等待队列的请求数量有限制

下面写了个小例子, 验证第三点

<!DOCTYPE html> <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> 复制代码

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('启动了') }) 复制代码

image.png image.png

第二种情况(同时发大量请求, 一千多个)几乎不会出现, 所以针对第一种情况(浏览器同时只发送 6 个请求)需要对一些不重要的请求(比如预加载一百张图片)进行限流, 防止阻塞重要的请求(比如用户签到).

实现

思路

  1. 肯定得有一个缓存器, 把那些还没有发送的请求存起来

  2. 肯定有个上限, 这个上限肯定比 6 小, 当正在请求数大于这个数时, 不再请求

代码

这里没有处理边界情况, 也没有处理报错, 只是简单的代码实现

class LimitRequest {   // 限制同时请求的数量   limitCount = 0   // 缓存还没有发送的请求   cacheRequest = []   // 当前正在请求的数量   currentRequest = 0   constructor(limitCount) {     this.limitCount = limitCount   }   /**    * 新增请求    * @param {*} fn    */   addRequest(fn) {     // 把这个请求缓存起来     this.cacheRequest.push(fn)     // 发送请求     // 这个发送请求可以不写, 由用户自己手动去调用     this.request()   }   /**    * 从缓存中拿出一条请求, 发送    */   async request() {     if (this.currentRequest >= this.limitCount) {       // 如果当前请求数量超出了限制, 不再发送新的请求       return     }     // 当前正在请求的数量加一     this.currentRequest++     // 拿出缓存的请求     const fn = this.cacheRequest.shift()     // 发送请求     await fn()     // 请求结束, 当前正在发送的请求减一     this.currentRequest--     // 空出一个名额, 可以再次请求     this.request()   } } 复制代码

完整代码

<!DOCTYPE html> <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 {         // 限制同时请求的数量         limitCount = 0         // 缓存还没有发送的请求         cacheRequest = []         // 当前正在请求的数量         currentRequest = 0         constructor(limitCount) {           this.limitCount = +limitCount || 3         }         /**          * 新增请求          * @param {*} fn          */         addRequest(fn) {           if (typeof fn !== 'function') {             console.log('addRequest添加请求需要传入函数')             return           }           // 把这个请求缓存起来           this.cacheRequest.push(fn)           // 修改, 这里不去调用了, 留着用户自己在合适的时机调用         }         /**          * 从缓存中拿出一条请求, 发送          */         async request() {           if (this.currentRequest >= this.limitCount) {             // 如果当前请求数量超出了限制, 不再发送新的请求             return           }           // 当前正在请求的数量加一           this.currentRequest++           // 这里是用户主动调的, 所以一次要请求到上限           this.request()           try {             // 拿出缓存的请求             const fn = this.cacheRequest.shift()             // 发送请求             await fn()           } catch (err) {             console.log('执行fn报错', err)           } finally {             // 请求结束, 当前正在发送的请求减一             this.currentRequest--             if (this.cacheRequest.length) {               // 空出一个名额, 并且还有请求, 可以再次请求               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(() => {         // 在3秒之后, 浏览器空闲了, 发送请求         limitRequest.request()       }, 3000)     </script>   </body> </html> 复制代码

最后

欢迎互动 欢迎加我微信呀~~~~


作者:__冬冬来了__
链接:https://juejin.cn/post/7015257618088198180

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐