Skip to content

Commit ae93299

Browse files
committed
chore: layout
1 parent e39dc5d commit ae93299

4 files changed

Lines changed: 185 additions & 188 deletions

File tree

JS/algorithm/pDd/2026春.js

Lines changed: 0 additions & 188 deletions
This file was deleted.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// 1. 事件监听机制
2+
function createEventBus() {
3+
this.listeners = new Map()
4+
}
5+
6+
// 只有_内部函数才能操作 listeners
7+
// 在内部用于添加回调函数的工具函数
8+
// 通过单调递增的 id 确保不会因为删除而有重复 id
9+
createEventBus.prototype._add = (event, handler, once) => {
10+
if (!this.listeners.has(event)) { // 初始化
11+
this.listeners.set(event, [0])
12+
}
13+
const pre = this.listeners.get(event)
14+
const newId = pre[0] + 1
15+
const curObj = {
16+
id: newId,
17+
handler: () => handler(),
18+
flag: once // 是否只执行一次就移除
19+
}
20+
const new = [...pre, curObj]
21+
new [0] = newId
22+
this.listeners.set(event, new)
23+
return newId // 返回 newId 用于删除
24+
}
25+
26+
// 在内部用于删除回调函数的工具函数
27+
createEventBus.prototype._delete = (event, id) => {
28+
const cur = this.listeners.get(event)
29+
if (cur[0] < id) return false // 如果最大的 id 都比当前输入的小,那么肯定输错了
30+
let targetIdx = -1
31+
for (let i = 0; i < cur.length; i++) {
32+
if (cur[i].id === id) {
33+
targetIdx = i
34+
break
35+
}
36+
}
37+
if (targetIdx === -1) return false
38+
const new = cur.splice(targetIdx, 1)
39+
this.listeners.set(event, new)
40+
return true // 删除成功
41+
}
42+
43+
createEventBus.prototype.on = function (event, handler) {
44+
if (!handler) return false // 特殊情况处理,防止执行空导致报错
45+
const newId = this._add(event, handler, false)
46+
return () => this._delete(event, newId)
47+
}
48+
49+
createEventBus.prototype.once = function (event, handler) {
50+
if (!handler) return false
51+
const newId = this._add(event, handler, true)
52+
return () => this._delete(event, newId)
53+
}
54+
55+
createEventBus.prototype.emit = function (event, ...args) {
56+
const arr = this.listeners.get(event)
57+
for (const item of arr) {
58+
item.handler(args)
59+
if (item.once) {
60+
this._delete(event, item.id)
61+
}
62+
}
63+
}
64+
// 思路:内部通过listeners映射维护监听者数组,并且
65+
// 只有_内部函数才能操作 listeners
66+
// 在内部用于添加回调函数的工具函数
67+
// 通过单调递增的 id 确保不会因为删除而有重复 id
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// 2. 新旧数组比较
2+
function diffList(oldList, newList, key) {
3+
const ans = {
4+
added: [],
5+
removed: [],
6+
changed: []
7+
}
8+
9+
const LO = oldList.length
10+
const LN = newList.length
11+
oldList.sort((a, b) => a.id - b.id)
12+
newList.sort((a, b) => a.id - b.id)
13+
let oldPtr = 0
14+
let newPtr = 0
15+
while (oldPtr < LO && newPtr < LN) {
16+
const old = oldList[oldPtr]
17+
const new = newList[newPtr]
18+
if (old.id === new.id) {
19+
const fields = []
20+
// 因为我看题目没有说新增字段,所以就直接取旧对象的属性进行比较
21+
const keys = Object.keysOf(old)
22+
for (const key of keys) {
23+
if (old[key] !== new [key]) {
24+
fields.push({
25+
field: key,
26+
oldVal: old[key],
27+
newVal: new [key]
28+
})
29+
}
30+
}
31+
ans.changed.push({
32+
id: old.id,
33+
fields: fields
34+
})
35+
oldPtr++
36+
newPtr++
37+
}
38+
else if (old.id < new.id) {
39+
ans.removed.push(old)
40+
oldPtr++
41+
}
42+
else if (old.id > new.id) {
43+
ans.added.push(new)
44+
newPtr++
45+
}
46+
}
47+
48+
// 剩余情况处理
49+
while (oldPtr < LO) {
50+
ans.removed.push(oldList[oldPtr])
51+
oldPtr++
52+
}
53+
while (newPtr < LN) {
54+
ans.added.push(newList[newPtr])
55+
newPtr++
56+
}
57+
58+
return ans
59+
}
60+
// 思路:双指针比较,利用排序后的id进行判断是哪种类型的变更
61+
// 并且题目说层数只需要一层,所以也不用写边界条件去递归DFS
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// 3. 要求实现一个有缓存、不会重复发送请求、超时报错的请求函数
2+
function createCachedRequest(requestFn, options = {}) {
3+
const memo = new Map()
4+
const ttl = options.ttl ? options.ttl : 5000
5+
const timeout = options.timeout
6+
const curTasks = new Map() // 保存异步任务Promise,防止多次请求
7+
8+
return async (key) => {
9+
if (memo.has(key)) {
10+
const memoObj = memo.get(key)
11+
const lastTime = memoObj.get(time)
12+
if (Date.now() - lastTime < ttl) {
13+
return memoObj.val // 命中缓存
14+
}
15+
}
16+
if (curTasks.has(key)) { // 前面已经有一次请求
17+
const res = await curTasks.get(key)
18+
if (res === 'Timeout') return 'Timeout' // 如果超时就不走下面缓存
19+
memo.set(key, {
20+
time: Date.now(),
21+
val: res
22+
})
23+
return res
24+
}
25+
if (!timeout) {
26+
curTasks.set(key, async () => {
27+
return await requestFn(key)
28+
})
29+
const res = await curTasks.get(key) // 没设置timeout不可能超时
30+
memo.set(key, {
31+
time: Date.now(),
32+
val: res
33+
})
34+
return res
35+
}
36+
else {
37+
curTasks.set(key, () => new Promise(
38+
(resolve, reject) => {
39+
// 利用 Promise 状态只可能改变一次,同时使用 reject 和 resolve
40+
setTimeout(() => {
41+
reject('Timeout')
42+
}, timeout)
43+
const res = requestFn(key)
44+
resolve(res)
45+
}
46+
))
47+
const res = await curTasks.get(key)
48+
if (res === 'Timeout') return 'Timeout'
49+
memo.set(key, {
50+
time: Date.now(),
51+
val: res
52+
})
53+
return res
54+
}
55+
}
56+
}
57+
// 思路:通过 memo 管理缓存,通过 async, await语法糖 以及 Promise 管理异步

0 commit comments

Comments
 (0)