基于Q框架动态创建Promise序列并传参的进阶实现问询
嘿,恭喜你已经搞定了基础的Promise串行序列!针对你提到的更复杂的同类需求,我整理了几个常见场景的实现方案,你可以根据自己的具体需求灵活调整:
1. 带条件分支的Promise序列
如果某些步骤需要根据前一个结果选择不同的后续逻辑(比如分支执行不同的Promise函数),用async/await循环会比reduce更直观,方便插入条件判断:
// 带条件分支的串行序列执行函数 const runConditionalSequence = async (actions, initialValue) => { let currentResult = initialValue; for (const action of actions) { currentResult = await action(currentResult); // 根据当前结果触发分支逻辑 if (currentResult.isSpecialCase) { // 执行分支专属的Promise函数 currentResult = await specialBranchAction(currentResult); // 可选:跳过后续部分步骤 continue; } // 其他条件判断... if (currentResult.skipNext) { actions.splice(actions.indexOf(action) + 1, 1); // 移除下一个步骤 } } return currentResult; }; // 示例分支函数 const specialBranchAction = (prevResult) => { return Promise.resolve({ ...prevResult, branchCompleted: true }); };
2. 保留所有历史结果的串行序列
如果后续步骤需要依赖之前所有步骤的结果(而不只是前一个),可以维护一个历史结果数组,把整个数组传递给每个Promise函数:
// 保留历史结果的串行序列 const runSequenceWithHistory = async (actions, initialValue) => { const history = initialValue !== undefined ? [initialValue] : []; return actions.reduce(async (prevPromise, currentAction) => { await prevPromise; // 等待上一个步骤完成 const newResult = await currentAction(history); // 传入全部历史结果 history.push(newResult); return newResult; }, Promise.resolve()); }; // 示例依赖历史结果的action const calculateTotal = (history) => { const sum = history.reduce((acc, item) => acc + item.value, 0); return Promise.resolve({ type: 'total', value: sum }); };
3. 可中断/带容错的Promise序列
如果需要在某个步骤失败或满足特定条件时终止整个序列,或者容错处理后继续执行,可以在循环中加入错误捕获和中断判断:
// 可中断+容错的串行序列 const runInterruptibleSequence = async (actions, initialValue) => { let currentResult = initialValue; for (const action of actions) { try { currentResult = await action(currentResult); // 满足中断条件时停止执行 if (currentResult.shouldStop) { console.log('序列已主动中断'); break; } } catch (err) { console.error(`步骤执行失败: ${err.message}`); // 可选:容错处理,用默认值继续 currentResult = { fallbackValue: true }; // 或者:直接终止序列,抛出错误 // throw new Error('序列执行失败,终止'); } } return currentResult; };
4. 带重试机制的串行步骤
如果某个步骤可能偶发失败,需要自动重试后再继续,可以给目标action包装一层重试逻辑:
// 重试工具函数:包装需要重试的action const withRetry = (action, maxRetries = 3, delay = 1000) => { return async (prevResult) => { let attempts = 0; while (attempts < maxRetries) { try { return await action(prevResult); } catch (err) { attempts++; console.log(`重试第${attempts}次,错误: ${err.message}`); if (attempts === maxRetries) throw err; // 重试耗尽,抛出错误 await new Promise(resolve => setTimeout(resolve, delay)); // 延迟重试 } } }; }; // 使用示例:给f2添加重试逻辑 const actionsWithRetry = [f1, withRetry(f2), f3]; // 用你原来的序列执行函数即可 runSequence(actionsWithRetry);
5. 动态添加步骤的串行序列
如果需要在执行过程中,根据某个步骤的结果动态插入新的Promise函数,可以用队列+循环的方式实现:
// 动态添加步骤的串行序列 const runDynamicSequence = async (initialActions, initialValue) => { const actionQueue = [...initialActions]; let currentResult = initialValue; while (actionQueue.length > 0) { const currentAction = actionQueue.shift(); currentResult = await currentAction(currentResult); // 根据结果动态添加新步骤到队列 if (currentResult.newActions) { actionQueue.push(...currentResult.newActions); delete currentResult.newActions; // 避免重复添加 } } return currentResult; }; // 示例动态添加步骤的action const checkNeedMoreSteps = (prevResult) => { if (prevResult.data.length < 10) { return Promise.resolve({ ...prevResult, newActions: [fetchMoreData, processMoreData] // 动态插入两个新步骤 }); } return Promise.resolve(prevResult); };
如果你的需求是上述场景之外的更特殊情况,可以补充具体细节,我们再细化方案~
内容的提问来源于stack exchange,提问作者François Richard
相关产品推荐
相关产品推荐

