Skip to content

Commit 453ece7

Browse files
committed
feat: 优先级任务队列的三种实现方式
1 parent e0590f2 commit 453ece7

1 file changed

Lines changed: 215 additions & 0 deletions

File tree

JS/algorithm/lazyman.js

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// === 1 ===
2+
// Promise 链实现:通过维护一个 promise 链,每次调用方法追加 .then()
3+
function LazyManPromise(name) {
4+
this.name = name
5+
// 维护 this.promise 延迟启动的 Promise 作为链的起点,确保链式调用全部完成后,再开始执行任务
6+
// new Promise() 创建时 立即执行 executor 函数
7+
this.promise = new Promise(resolve => {
8+
setTimeout(() => {
9+
console.log(`I am ${this.name}`)
10+
resolve()
11+
}, 0)
12+
})
13+
}
14+
15+
LazyManPromise.prototype.rest = function (time) {
16+
// 在现有 Promise 链后追加新的异步操作
17+
this.promise = this.promise.then(() => {
18+
return new Promise(resolve => {
19+
setTimeout(() => {
20+
console.log(`Wake up after ${time}s`)
21+
resolve()
22+
}, time * 1000)
23+
})
24+
})
25+
return this // 返回 this 支持链式调用
26+
}
27+
28+
LazyManPromise.prototype.firstRest = function (time) {
29+
// 创建新的 Promise 链,将原链追加到后面
30+
const oldPromise = this.promise
31+
this.promise = new Promise(resolve => {
32+
setTimeout(() => {
33+
console.log(`Wake up after ${time}s`)
34+
resolve()
35+
}, time * 1000)
36+
}).then(() => oldPromise)
37+
return this
38+
}
39+
40+
LazyManPromise.prototype.learn = function (what) {
41+
this.promise = this.promise.then(() => {
42+
console.log(`Learning ${what}`)
43+
})
44+
return this
45+
}
46+
47+
function HardmanPromise(name) {
48+
return new LazyManPromise(name)
49+
}
50+
51+
console.log('=== Promise 链实现 ===')
52+
HardmanPromise("Tom").rest(1).learn("Math")
53+
54+
setTimeout(() => {
55+
console.log('\n=== Promise firstRest 测试 ===')
56+
HardmanPromise("Jack").firstRest(1).learn("English")
57+
}, 3000)
58+
59+
60+
// === 2 ===
61+
// 通过 任务队列task,next() 进行管理
62+
function LazyMan(name) {
63+
this.name = name
64+
this.task = [() => {
65+
console.log(`I am ${this.name}`)
66+
this.next() // 执行完后继续下一个任务
67+
}]
68+
69+
// 延迟启动,确保链式调用完成后再执行
70+
setTimeout(() => {
71+
this.next()
72+
}, 0)
73+
}
74+
75+
// 执行下一个任务
76+
LazyMan.prototype.next = function () {
77+
const task = this.task.shift()
78+
task && task.call(this) // 使用 call 绑定 this
79+
}
80+
81+
LazyMan.prototype.rest = function (time) {
82+
this.task.push(() => {
83+
setTimeout(() => {
84+
console.log(`Wake up after ${time}s`)
85+
this.next() // 休息结束后继续执行
86+
}, time * 1000)
87+
})
88+
return this // 返回this进而支持装饰器模式链式调用,例如 .rest(time).rest()/.learn
89+
}
90+
91+
LazyMan.prototype.firstRest = function (time) {
92+
this.task.unshift(() => {
93+
setTimeout(() => {
94+
console.log(`Wake up after ${time}s`)
95+
this.next()
96+
}, time * 1000)
97+
})
98+
return this
99+
}
100+
101+
LazyMan.prototype.learn = function (what) {
102+
this.task.push(() => {
103+
console.log(`Learning ${what}`)
104+
this.next() // 执行完后继续
105+
})
106+
return this
107+
}
108+
109+
// 工厂函数
110+
function Hardman(name) {
111+
return new LazyMan(name)
112+
}
113+
114+
// 测试
115+
console.log('=== 原型链实现 ===')
116+
Hardman("jack").rest(2).learn("computer")
117+
118+
119+
// === 3 ===
120+
// 任务队列的类实现
121+
class LazyMan2 {
122+
constructor(name) {
123+
this.name = name
124+
this.tasks = [] // 任务队列
125+
126+
// 添加初始任务
127+
this.tasks.push(() => {
128+
console.log(`I am ${this.name}`)
129+
this.next()
130+
})
131+
132+
// 在下一个事件循环中开始执行任务队列
133+
setTimeout(() => {
134+
this.next()
135+
}, 0)
136+
}
137+
138+
// 执行下一个任务
139+
next() {
140+
const task = this.tasks.shift()
141+
task && task()
142+
}
143+
144+
// 休息
145+
rest(time) {
146+
this.tasks.push(() => {
147+
setTimeout(() => {
148+
console.log(`Wake up after ${time}s`)
149+
this.next()
150+
}, time * 1000)
151+
})
152+
return this // 返回 this 支持链式调用
153+
}
154+
155+
// 优先休息(插入队列头部)
156+
firstRest(time) {
157+
this.tasks.unshift(() => {
158+
setTimeout(() => {
159+
console.log(`Wake up after ${time}s`)
160+
this.next()
161+
}, time * 1000)
162+
})
163+
return this
164+
}
165+
166+
// 学习
167+
learn(subject) {
168+
this.tasks.push(() => {
169+
console.log(`Learning ${subject}`)
170+
this.next()
171+
})
172+
return this
173+
}
174+
175+
// 吃东西
176+
eat(food) {
177+
this.tasks.push(() => {
178+
console.log(`Eat ${food}`)
179+
this.next()
180+
})
181+
return this
182+
}
183+
}
184+
185+
// 工厂函数
186+
function Hardman2(name) {
187+
return new LazyMan2(name)
188+
}
189+
190+
// 测试用例
191+
console.log('=== Test 1 ===')
192+
Hardman2("jack").rest(2).learn("computer")
193+
/*打印:
194+
I am jack
195+
Wake up after 2s
196+
Learning computer */
197+
198+
// setTimeout(() => {
199+
// console.log('\n=== Test 2 ===')
200+
// Hardman("jack").firstRest(2).learn("computer")
201+
// /* 打印:
202+
// Wake up after 2s
203+
// I am jack
204+
// Learning computer */
205+
// }, 5000)
206+
207+
// setTimeout(() => {
208+
// console.log('\n=== Test 3 ===')
209+
// Hardman("Tom").eat("lunch").rest(1).learn("English")
210+
// /* 打印:
211+
// I am Tom
212+
// Eat lunch
213+
// Wake up after 1s
214+
// Learning English */
215+
// }, 10000)

0 commit comments

Comments
 (0)