手撕代码系列(四)
手写触发控制器 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();
});
}
}
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();
统计页面中前三个标签出现的个数
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(',');
new Set([...document.querySelectorAll('*')].map(tag => tag.tagName));
Object.entries(
[...document.querySelectorAll('*')]
.map(tag => tag.tagName)
.reduce((prev, next) => {
prev[next] = (prev[next] || 0) + 1;
return prev;
}, {})
);
实现菲波那切数列 factorial
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
console.log('factorial(5)', factorial(3));
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 {
if (this.cache.size >= this.max) {
this.cache.delete(this.cache.keys().next().value);
}
}
this.cache.set(key, value);
}
}
let lRUCache = new LRUCache(2);
lRUCache.put(1, 1);
lRUCache.put(2, 2);
lRUCache.get(1);
lRUCache.put(3, 3);
lRUCache.get(2);
lRUCache.put(4, 4);
lRUCache.get(1);
lRUCache.get(3);
lRUCache.get(4);
console.log(lRUCache.cache.size);
使用 setInterVal 实现 setTimeout
const MySetTimeout = (fn, time = 400) => {
let timer = setInterval(() => {
fn();
clearInterval(timer);
}, time);
};
MySetTimeout(() => {
console.log('12132');
}, 3000);
使用 setTimeout 实现 setInterVal
function MysetInterVal(fn, timeout = 1500) {
let timer = null;
const interval = () => {
fn();
timer = setTimeout(interval, timeout);
};
setTimeout(interval, timeout);
return {
cancel: () => {
clearTimeout(timer);
},
};
}
let { cancel } = MysetInterVal(() => console.log(454545), 1500);
setTimeout(() => {
cancel();
}, 4000);
特殊字符描述:
- 问题标注
Q:(question)
- 答案标注
R:(result)
- 注意事项标准:
A:(attention matters)
- 详情描述标注:
D:(detail info)
- 总结标注:
S:(summary)
- 分析标注:
Ana:(analysis)
- 提示标注:
T:(tips)
打开App,阅读手记