promise本身不支持优先级调度,但可通过最小堆实现优先级任务队列,按priority升序执行任务对象{priority,task},保证链式调用且不中断已运行promise。

Promise 本身不直接支持优先级调度,但可以通过封装一个带优先级的任务队列(Priority Queue)来实现:把 Promise 创建逻辑和优先级绑定,按优先级顺序执行,同时保证每个任务仍以 Promise 形式返回和链式调用。
核心思路:用最小堆管理待执行任务
优先级队列底层推荐使用最小堆(小的数字代表高优先级,比如 0 最高,10 最低),每次 run() 只取出堆顶任务执行。关键不是“中断正在运行的 Promise”,而是“控制入队和出队顺序”,因为 Promise 一旦开始执行就不可取消(除非手动加 abort 逻辑)。
- 每个任务包装为对象:
{ priority: number, task: () => Promise<any> }</any> - 入队时插入堆中,按
priority排序 - 出队时总是取最小 priority 的任务执行,并返回其 Promise 结果
- 支持链式调用:
queue.add(() => fetch(...), 1).then(...)
简易可运行实现(无第三方依赖)
以下是一个轻量、可直接使用的优先级 Promise 队列:
class PriorityQueue {
constructor() {
this.heap = [];
}
<p>_swap(i, j) {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}</p><p>_heapifyUp(index) {
while (index > 0) {
const parent = Math.floor((index - 1) / 2);
if (this.heap[parent].priority </p><p>_heapifyDown(index) {
const len = this.heap.length;
while (true) {
let smallest = index;
const left = 2 <em> index + 1;
const right = 2 </em> index + 2;
if (left </p><p>add(task, priority = 0) {
const item = { priority, task };
this.heap.push(item);
this._heapifyUp(this.heap.length - 1);
return this.run(); // 返回该任务的 Promise,支持 .then
}</p><p>run() {
if (this.heap.length === 0) return Promise.resolve();
const top = this.heap[0];
this._swap(0, this.heap.length - 1);
this.heap.pop();
this._heapifyDown(0);</p><pre class="brush:php;toolbar:false;">return Promise.resolve().then(() => top.task());} }
使用示例:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
const queue = new PriorityQueue(); <p>// 高优先级:立刻尝试登录 queue.add(() => api.login(), 0).then(console.log);</p><p>// 低优先级:稍后同步日志 queue.add(() => api.uploadLogs(), 5).then(console.log);</p><p>// 中优先级:获取用户信息 queue.add(() => api.fetchUser(), 2).then(console.log); // 实际执行顺序:login → fetchUser → uploadLogs</p>
进阶:支持并发数限制 + 取消能力
真实场景常需控制最大并发数(如最多同时跑 3 个请求),并允许取消低优先级等待中的任务:
- 维护一个
runningCount计数器,仅当才 <code>run() - 给每个任务附加
AbortController,在新高优任务入队时,主动abort()当前低优待执行任务(需 task 函数内部配合使用 signal) - 暴露
clear(priorityThreshold)方法,清掉所有 priority ≥ 某值的待执行任务
例如:queue.clear(3) 可丢弃所有优先级为 3 及更低的排队任务,避免积压。
注意事项与边界情况
要避免几个常见误区:
- Promise 一旦
.then或await就已进入微任务队列,无法靠队列“插队”改变执行时机 —— 优先级只作用于“何时开始执行”,而非“何时 resolve” - 不要在 task 函数里直接 throw 错误,应统一由队列捕获并 reject,否则会丢失错误上下文
- 如果 task 返回非 Promise,需用
Promise.resolve(task())包装,保持行为一致 - 多个相同优先级任务按插入顺序 FIFO 执行(堆内可加插入时间戳作为第二排序键)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










