写点什么

手撕代码系列 (四)

作者:控心つcrazy
  • 2023-05-02
    广东
  • 本文字数:3026 字

    阅读完需:约 10 分钟

手撕代码系列(四)

前言

系列首发于公众号『前端进阶圈』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。

手撕代码系列(四)

手写触发控制器 Scheduler

  • 当资源不足时将任务加入队列,当资源足够时,将等待队列中的任务取出执行

  • 任务调度器-控制任务的执行,当资源不足时将任务加入等待队列,当资源足够时,将等待队列中的任务取出执行

  • 在调度器中一般会有一个等待队列queue,存放当资源不够时等待执行的任务。

  • 具有并发数据限制,假设通过max设置允许同时运行的任务,还需要count表示当前正在执行的任务数量。

  • 当需要执行一个任务 A 时,先判断count==max 如果相等说明任务 A 不能执行,应该被阻塞,阻塞的任务放进queue中,等待任务调度器管理。

  • 如果 count< max 说明正在执行的任务数没有达到最大容量,那么count++执行任务 A,执行完毕后count--

  • 此时如果queue中有值,说明之前有任务因为并发数量限制而被阻塞,现在count < max,任务调度器会将对头的任务弹出执行。


class Scheduler {    constructor(max) {        this.queue = [];        this.max = max;        this.count = 0;    }
add(time, order) { const promise = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log(order); resolve(); }, time); }); }; this.queue.push(promise); }
start() { for (let i = 0; i < this.max; i++) { this.request(); } }
request() { if (!this.queue.length || this.count >= this.max) return; this.count++; this.queue .shift()() .then(() => { this.count--; this.request(); }); }}
// test:let scheduler = new Scheduler(2);scheduler.add(2000, '1');scheduler.add(200, '2');scheduler.add(500, '3');scheduler.add(800, '4');scheduler.add(1200, '5');scheduler.start(); // 2 3 4 1 5
复制代码

统计页面中前三个标签出现的个数

/** * 统计前三的标签 * * @logic *  1.先拿到所有标签的标签名 *  2.对每个标签进行统计 *  3.倒序 *  4.截取前三项即可 */Object.entries(    [...document.querySelectorAll('*')]        .map(tag => tag.tagName)        .reduce((ret, i) => {            ret[i] = (ret[i] || 0) + 1;            return ret;        }, {}))    .sort((a, b) => b[1] - a[1])    .slice(0, 3)    .map(item => `${item[0]}: ${item[1]}`)    .join(',');
// test:// [// ['SPAN', 451],// ['A', 135],// ['DIV', 106]// ]
// 统计页面中使用到的标签new Set([...document.querySelectorAll('*')].map(tag => tag.tagName));// Set(37) {'HTML', 'RELINGO-APP', 'DIV', 'HEAD', 'META', …}
// 统计每个标签使用的个数Object.entries( [...document.querySelectorAll('*')] .map(tag => tag.tagName) .reduce((prev, next) => { prev[next] = (prev[next] || 0) + 1; return prev; }, {}));
// test:// [// ['HTML', 1]// ['RELINGO-APP', 2]// ['DIV', 106]// ['HEAD', 1]// ['META', 7]// ['TITLE', 1]// ['LINK', 71]// ['SCRIPT', 8]// ]
复制代码

实现菲波那切数列 factorial

function factorial(n) {    if (n <= 1) return 1;
// return fibonacci(n - 1) + fibonacci(n - 2); return n * factorial(n - 1);}
// test:console.log('factorial(5)', factorial(3)); // 6
复制代码

lru-缓存

  • lru 是近期最少使用的缓存对象,核心是想要淘汰掉近期使用较少的对象


class LRUCache {    constructor(capacity) {        this.cache = new Map();        this.max = capacity;    }
get(key) { if (this.cache.has(key)) { let temp = this.cache.get(key); // 删除当前项 this.cache.delete(key); // 将当前项移到最前面 this.cache.set(key, temp); return temp; } return -1; }
put(key, value) { if (this.cache.has(key)) { this.cache.delete(key); } else { // 如果缓存数 >= this.max 然后执行淘汰机制 // this.cache.keys().next().value:cache 中第一个值 if (this.cache.size >= this.max) { this.cache.delete(this.cache.keys().next().value); } } this.cache.set(key, value); }}
// test:let lRUCache = new LRUCache(2);lRUCache.put(1, 1); // 缓存是 {1=1}lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}lRUCache.get(1); // 返回 1lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {3=3, 1=1}lRUCache.get(2); // 返回 -1 (未找到)lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}lRUCache.get(1); // 返回 -1 (未找到)lRUCache.get(3); // 返回 3lRUCache.get(4); // 返回 4console.log(lRUCache.cache.size);
复制代码

使用 setInterVal 实现 setTimeout

/** * @param {Function} fn 方法 * @param {Number} time 间隔时间 */const MySetTimeout = (fn, time = 400) => {    let timer = setInterval(() => {        fn();        clearInterval(timer);    }, time);};
// test:MySetTimeout(() => { console.log('12132');}, 3000);
复制代码

使用 setTimeout 实现 setInterVal

/** * @param {Function} fn 方法 * @param {Number} timeout 间隔时间 */function MysetInterVal(fn, timeout = 1500) {    let timer = null;    const interval = () => {        fn();        timer = setTimeout(interval, timeout);    };
setTimeout(interval, timeout); return { cancel: () => { clearTimeout(timer); }, };}
// test:let { cancel } = MysetInterVal(() => console.log(454545), 1500);setTimeout(() => { cancel();}, 4000);
复制代码

特殊字符描述:

  1. 问题标注 Q:(question)

  2. 答案标注 R:(result)

  3. 注意事项标准:A:(attention matters)

  4. 详情描述标注:D:(detail info)

  5. 总结标注:S:(summary)

  6. 分析标注:Ana:(analysis)

  7. 提示标注:T:(tips)

往期推荐:

最后:

  • 欢迎关注 『前端进阶圈』 公众号 ,一起探索学习前端技术......

  • 公众号回复 加群扫码, 即可加入前端交流学习群,一起快乐摸鱼和学习......

  • 公众号回复 加好友,即可添加为好友

发布于: 刚刚阅读数: 2
用户头像

还未添加个人签名 2021-10-17 加入

还未添加个人简介

评论

发布
暂无评论
手撕代码系列(四)_JavaScript_控心つcrazy_InfoQ写作社区