多加载器
AsyncLoader 的第一个参数 loader 支持传入数组,由 multiLoaderStrategy 选项决定如何编排多个加载函数:备用容灾(fallback)或多源合并(combine)。多 loader 场景同样复用缓存 / 中止 / 超时 / 重试 / 兜底 / multiplex 全套能力。
fallback:备用容灾
顺序尝试 loaders,首个成功即停止后续;某 loader 失败则尝试下一个;全部失败才算本次加载失败。
typescript
import { AsyncLoader } from "asyncsignal/loader";
// 主接口失败时自动回退到备用接口
const loader = new AsyncLoader(
[
async (args) => (await fetch("/api/primary", { signal: args.abortSignal })).json(),
async (args) => (await fetch("/api/secondary", { signal: args.abortSignal })).json(),
async (args) => (await fetch("/api/cdn", { signal: args.abortSignal })).json(),
],
{ multiLoaderStrategy: "fallback", retry: 1 }
);
const data = await loader.get(); // 依次尝试,直到某个成功fallback 不调用 onResults
fallback 仅做"出错切换",不会调用 onResults(即使配置了也忽略)。onResults 是 combine 专用的结果合并 hook。
combine:多源合并
所有 loader 并发执行,结果(成功项为 T、失败项为 Error)收集后交给 onResults 合并返回。采用宽容语义(Promise.allSettled):单个 loader 失败不中断其他 loader,仅以 Error 形式进入 results。
typescript
// 并发请求用户信息与订单,合并成一个对象
const loader = new AsyncLoader(
[
async (args) => (await fetch("/api/user", { signal: args.abortSignal })).json(),
async (args) => (await fetch("/api/orders", { signal: args.abortSignal })).json(),
],
{
multiLoaderStrategy: "combine",
onResults: (results, defaultValue) => {
// 过滤出成功项合并;失败项为 Error 实例
const [user, orders] = results;
if (user instanceof Error || orders instanceof Error) {
return defaultValue as { user: any; orders: any }; // 部分失败时用兜底
}
return { user, orders };
},
}
);
const { user, orders } = await loader.get();onResults 详解
onResults(results, defaultValue) => T 是 combine 策略的结果合并 hook:
| 参数 | 说明 |
|---|---|
results | 全部 loader 的结果数组(顺序与 loaders 对应),成功项为 T,失败项为 Error 对象 |
defaultValue | options.defaultValue 配置的兜底值(可能 undefined),供 hook 决定是否兜底 |
- 返回合并后的最终结果
T,作为get()的返回值并写入缓存。 - 同步抛错视为本次加载失败(走
retry/onRejected/defaultValue终态逻辑)。 - 这是有返回值的转换函数(非事件回调),错误必须传播——不走
onFulfilled/onRejected的吞错机制。
combine 必须提供 onResults
multiLoaderStrategy="combine" 且 loader 数量 > 1 时,必须提供 onResults,否则构造抛错:multiLoaderStrategy="combine" requires onResults。
与其他能力的交互
| 能力 | 与多加载器的交互 |
|---|---|
timeout | per-attempt:多 loader 共享本次尝试的超时窗口(fallback/combine 均如此) |
retry | fallback 全部失败 / combine 最终失败(含 onResults 抛错)时,按 retry 重试整个 loaders 序列 |
abort() | 中止当前进行中的 loader(组);onRejected 由 abort() 同步触发 |
defaultValue | 既作为参数传给 onResults(供其决策),也在最终失败时作为兜底 resolve |
multiplex | 复用时以首个实例的 loaders 数组为准,新实例传入的 loader(s) 被忽略 |
hash | 基于 loaders 数组自动生成(顺序敏感:[a,b] 与 [b,a] 不同) |
单 loader 完全向后兼容
传入单个 loader(或单元素数组)时,multiLoaderStrategy 无效,行为与改造前完全一致。