不使用async/await实现高效Promise队列的方案探讨
实现支持动态添加Promise的队列(无async/await)
核心需求:队列在存在未解析的Promise时,允许持续添加新的Promise;且实现过程不使用async/await语法。
原方案的问题分析
你尝试通过给Promise.all传入自定义可迭代对象的思路无法满足需求,本质原因是**Promise.all会在调用时一次性完成对可迭代对象的遍历**,不会等待后续添加的元素。你的自定义迭代器虽然用了while(true),但第一次遍历结束后,Promise.all已经收集了所有当时队列中的Promise,后续添加的新Promise不会被纳入处理范围。
高效实现方法
方法1:链式Promise递归处理
通过维护一个持续延伸的Promise链,每次添加新Promise时将其追加到链的尾部,最终通过链的完成状态来返回所有结果。
class DynamicPromiseQueue { constructor() { // 初始化一个已完成的Promise作为链的起点 this._currentChain = Promise.resolve(); this._results = []; } add(promise) { // 将新Promise追加到当前链中,完成后记录结果 this._currentChain = this._currentChain.then(() => { return promise.then(result => { this._results.push(result); }); }); } all() { // 返回最终Promise,等待整个链完成后返回结果数组 return this._currentChain.then(() => [...this._results]); } }
工作原理:
- 每次调用
add时,新Promise会被链接到现有链的末尾,确保它会在之前的所有Promise完成后执行(此方案为串行处理,若需并行可调整逻辑)。 all方法返回的Promise会等待整个链的所有步骤完成,最终返回收集到的所有结果。
方法2:动态并行处理队列
通过递归处理队列,每次用Promise.all处理当前队列中的所有Promise,完成后再处理后续添加的新Promise,实现并行处理且支持动态添加。
class LazyParallelPromiseQueue { constructor() { this._queue = []; this._isProcessing = false; this._finalResolve = null; this._results = []; } add(promise) { this._queue.push(promise); // 若未在处理队列,启动处理流程 if (!this._isProcessing) { this._process(); } } _process() { this._isProcessing = true; // 取出当前队列的所有Promise,清空队列以接收新添加的 const currentPromises = [...this._queue]; this._queue = []; if (currentPromises.length === 0) { // 队列为空时,若有等待的最终Promise则触发resolve if (this._finalResolve) { this._finalResolve([...this._results]); this._finalResolve = null; } this._isProcessing = false; return; } // 并行处理当前所有Promise Promise.all(currentPromises) .then(results => { this._results.push(...results); // 递归处理新添加的Promise this._process(); }) .catch(error => { // 若需处理错误,可在此触发最终Promise的reject if (this._finalResolve) { this._finalResolve(Promise.reject(error)); this._finalResolve = null; } this._isProcessing = false; }); } all() { return new Promise(resolve => { this._finalResolve = resolve; // 若队列已空且未在处理,直接返回空结果 if (!this._isProcessing && this._queue.length === 0) { resolve([...this._results]); } }); } }
工作原理:
add方法将新Promise加入队列,若未启动处理则触发_process。_process取出当前队列的所有Promise并行处理,完成后收集结果并递归处理后续添加的Promise。all方法返回的Promise会等待所有队列中的Promise(包括后续动态添加的)全部完成后返回结果。
测试示例
以方法2为例,测试动态添加场景:
function timeout(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const queue = new LazyParallelPromiseQueue(); queue.add(timeout(1000)); setTimeout(() => { queue.add(timeout(1000)); queue.add(timeout(1000)); }, 500); // 不使用async/await的方式获取结果 queue.all().then(result => { console.log(result); // 约2秒后输出 [undefined, undefined, undefined] });
内容的提问来源于stack exchange,提问作者David Callanan
相关产品推荐
相关产品推荐

