综合应用篇
并发请求控制
js
class Scheduler {
constructor(n) {
this.max = n || 2;
this.num = 0;
this.task = []; // 当前执行任务队列
}
add(t) {
this.task.push(t);
this.run();
}
run() {
if (this.num < this.max && this.task.length) {
this.num++;
const fn = this.task.shift();
// 考虑优先级的话,排个序再取出
// const { fn } = this.task.sort((a, b) => b.priority - a.priority).shift();
fn()
.then(() => {
this._next();
})
.catch(() => {
this._next();
});
}
}
_next() {
this.num--;
this.run();
}
}
大数相加
js
// leetcode 415
function addStrings(num1, num2) {
let i = num1.length - 1;
let j = num2.length - 1;
let add = 0;
const ans = [];
while (i >= 0 || j >= 0 || add > 0) {
const a = i >= 0 ? Number(num1[i]) : 0;
const b = j >= 0 ? Number(num2[j]) : 0;
const res = a + b + add;
ans.push(res % 10);
add = Math.floor(res / 10);
i--;
j--;
}
return ans.reverse().join("");
}
数组和树转换
js
function list2Tree(list) {
// 用于 id 和 treeNode 的映射
const nodeMap = new Map();
let root = null;
list.forEach((item) => {
nodeMap.set(item.id, item);
});
list.forEach((item) => {
const { parentId } = item;
// 找到根节点
if (parentId === -1) {
root = item;
return;
}
// 找到 parentNode 并加入到它的 children
const parentNode = nodeMap.get(parentId);
if (parentNode) {
!parentNode.children && (parentNode.children = []);
parentNode.children.push(item);
}
});
return root;
}
function tree2List(root) {
const res = [];
const queue = [root];
while (queue.length) {
const node = queue.pop();
if (!node) break;
const { id, name, parentId, children = [] } = node;
res.push({ id, name, parentId });
children.forEach((child) => {
queue.unshift(child);
});
}
return res;
}
解析 url 参数为对象
js
// one-line
Object.fromEntries(new URLSearchParams(location.search));
LazyMan
js
/**
* @desc 手写 LazyMan ,实现 sleep 和 eat 两个方法,支持链式调用
*/
export class LazyMan {
constructor(name) {
this.name = name;
this.tasks = [];
// 调用
setTimeout(() => {
this._next();
});
}
_next() {
const task = this.tasks.shift();
task && task();
}
eat(foot) {
const task = () => {
console.log(`${this.name} is eating ${foot}`);
this._next();
};
this.tasks.push(task);
return this;
}
sleep(time) {
const task = () => {
setTimeout(() => {
console.log(`${this.name} sleep ${time}s`);
this._next();
}, 1000 * time);
};
this.tasks.push(task);
return this;
}
}
CSS解析器
js
function parseCSS(css) {
// 存储解析后的样式
const styles = {};
// 正则表达式,用于分离样式规则和属性
const pattern = /([^{]+)\{([^}]+)\}/g;
// 正则表达式,用于分离样式规则中的选择器和样式属性
const selectorPattern = /([^,]+),?/g;
const propertyPattern = /([^:]+):([^;]+);?/g;
// 分离样式规则和属性
const matches = css.matchAll(pattern);
for (const match of matches) {
const selectorMatch = match[1].matchAll(selectorPattern);
const propertiesMatch = match[2].matchAll(propertyPattern);
for (const selector of selectorMatch) {
const properties = {};
for (const property of propertiesMatch) {
properties[property[1].trim()] = property[2].trim();
}
styles[selector[1].trim()] = properties;
}
}
return styles;
}