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 <= this.heap[index].priority) break;
this._swap(parent, index);
index = parent;
}
}</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 < len && this.heap[left].priority < this.heap[smallest].priority) smallest = left;
if (right < len && this.heap[right].priority < this.heap[smallest].priority) smallest = right;
if (smallest === index) break;
this._swap(index, smallest);
index = smallest;
}
}</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());} }
使用示例:
立即学习“Java免费学习笔记(深入)”;
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
进阶:支持并发数限制 + 取消能力
真实场景常需控制最大并发数(如最多同时跑 3 个请求),并允许取消低优先级等待中的任务:
- 维护一个
runningCount计数器,仅当< maxConcurrent才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 执行(堆内可加插入时间戳作为第二排序键)


















