- base::Promise对象
梗概
Promise 的链式调用特性可以用来实现一个简单的任务队列,让异步任务按顺序一个接一个地执行,避免回调地狱。
实现原理
Promise 链式调用的特点:
- 每个 Promise 的 then/catch 方法都会返回一个新的 Promise
- 后续 Promise 会等待前一个 Promise 解决后才执行
- 可以通过不断链接 then 方法来构建顺序执行的任务
实现方式
基本任务队列
// 创建一个初始 Promise
let taskQueue = Promise.resolve();
// 添加任务到队列
function addTask(task) {
taskQueue = taskQueue.then(() => task());
return taskQueue; // 返回任务队列以便链式调用
}
// 使用示例
addTask(() => console.log("Task 1"));
addTask(() => new Promise(resolve => {
setTimeout(() => {
console.log("Task 2");
resolve();
}, 1000);
}));
addTask(() => console.log("Task 3"));
// 输出:
// Task 1
// (1秒后) Task 2
// Task 3带有结果收集的任务队列
class TaskQueue {
constructor() {
this.queue = Promise.resolve();
this.results = [];
}
addTask(task) {
this.queue = this.queue.then(async () => {
const result = await task();
this.results.push(result);
return result;
}).catch(error => {
console.error("Task failed:", error);
this.results.push(null); // 或者其他错误标识
// 不抛出错误,继续执行后续任务
});
return this;
}
async runAll() {
await this.queue;
return this.results;
}
}
// 使用示例
const queue = new TaskQueue();
queue.addTask(() => Promise.resolve("Result 1"))
.addTask(() => new Promise(resolve => setTimeout(() => resolve("Result 2"), 1000)))
.addTask(() => "Result 3");
queue.runAll().then(results => {
console.log("All tasks completed with results:", results);
});带控制流的任务队列
class AdvancedTaskQueue {
constructor() {
this.queue = Promise.resolve();
this.paused = false;
this.tasks = [];
}
addTask(task) {
this.tasks.push(task);
if (!this.paused) {
this._runNext();
}
return this;
}
_runNext() {
if (this.tasks.length === 0 || this.paused) return;
const task = this.tasks.shift();
this.queue = this.queue.then(() => {
return task();
}).then(() => {
if (!this.paused) {
this._runNext();
}
}).catch(error => {
console.error("Task error:", error);
if (!this.paused) {
this._runNext();
}
});
}
pause() {
this.paused = true;
return this;
}
resume() {
if (this.paused) {
this.paused = false;
this._runNext();
}
return this;
}
clear() {
this.tasks = [];
return this;
}
}应用场景
- 顺序处理 API 请求
- 文件上传队列
- 动画序列
- 复杂的初始化流程
- 数据处理流水线
注意事项
- 单一错误不会中断整个队列,但需要适当处理错误
- 大量任务可能导致内存占用,考虑分批执行
- 任务队列应该有暂停、恢复和清空的机制
- 考虑添加超时处理或重试机制
相关概念
- child::Promise对象 语法
- child::Promise的then方法
- child::Promise的catch方法