You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免fp-ts中TE.traverseArray遇Either Left时短路?

问题分析与解决方案

首先修正你代码里的语法错误:safeImport的定义多了一个右括号,正确写法是:

const safeImport = TE.tryCatchK((s) => import(s), tError);

两种写法输出差异的原因

你看到的输出差异,核心是TE.traverseArray的特性导致的:

  • TE.traverseArray是短路式遍历——它的作用是把Array<T>转换为TaskEither<E, Array<A>>,只要数组中有一个元素处理失败(返回Left),整个操作会立刻返回这个Left,不会继续处理后续元素。所以你只看到了第一个失败的结果,其他成功的元素根本没被执行。
  • 第二种写法用A.map(safeImport)得到Array<TaskEither<E, A>>,每个元素都是独立的异步Either操作,后续的A.map(async x => console.log(await x()))会逐个执行所有操作,不管前面的元素成功或失败,因此能看到所有Left和Right。

实现“保留所有Left和Right”的需求

如果你想保留所有元素的成功/失败状态,同时将批量异步操作的结果统一收集,可以这样写:

const tError = (err) => err instanceof Error ? err : Error("unexpected error");
const safeImport = TE.tryCatchK((s) => import(s), tError);

export const run = (globString) => pipe(
  glob.sync(globString),
  A.map(safeImport), // 得到 Array<TaskEither<E, A>>
  // 并行执行所有异步操作,收集所有结果
  TE.parArray(Infinity),
  async (tasks) => {
    const allResults = await tasks();
    console.log(allResults);
    // allResults 是 Array<Either<E, A>>,包含所有 Left 和 Right
    return allResults;
  }
);

或者用更直观的Promise.all实现:

export const run = (globString) => pipe(
  glob.sync(globString),
  A.map(safeImport),
  A.map(TE.toPromise), // 把 TaskEither 转为 Promise<Either<E,A>>
  Promise.all,
  async (allResults) => {
    console.log(allResults);
    return allResults;
  }
);

内容的提问来源于stack exchange,提问作者Ricardo Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:01:55