@effectionx/context-api

中文文档
0.6.0发布于 2026/04/10MITTypeScriptES Module构建来源已验证近 30 天下载 5.9万

具有中间软件的上下文操作的代数效应模式

中文使用文档
文档目录9 节
  1. 快速启动
  2. 以中间软件环绕
  3. 最小/最大优先级
  4. 仪器
  5. 测试模拟
  6. 范围隔离
  7. API 密码
  8. createApi(name, handler)
  9. around(middlewares, options?)

上下文 APIs

具有中间软件的上下文操作的代数效应模式


通常称为"代数效应"或"文字效应",上下文APIs允许您 通过上下文访问一个操作,以方便(和 上下文)用中间软件包裹. 中间软件由 @effectionx/middleware 支持分/最大优先级 点菜.

快速启动

假设您想要定义一个日志操作, 其行为在 不同的环境。 基本表单将只记录值到控制台.

import { createApi } from "@effectionx/context-api";

export const logging = createApi("logging", {
  *log(...values: unknown[]) {
    console.log(...values);
  },
});

export const { log } = logging.operations;

现在您可以随意使用日志 API :

import { log } from "./logging.ts";

export function* op() {
  yield* log("I am in an operation");
}

以中间软件环绕

使用 around 功能可以将中间软件包围在操作周围。 这样吧 或替换 完全执行.

import { logging } from "./logging.ts";

function* initCustomLogging(externalLogger: { log(...values: unknown[]): void }) {
  yield* logging.around({
    *log([...values], next) {
      externalLogger.log(...values);
      // since we override the logger entirely, we do not invoke next
    },
  });
}

Middleware只在安装范围内有效——当 瞄准镜出口,中间软件被取出.

最小/最大优先级

默认, around() 注册中间软件于 "max" 优先级(最多, 与来电者相近. 您也可在 "min" 优先级( 最大, 最接近核心处理器),通过传递选项参数:

import { createApi } from "@effectionx/context-api";
import type { Operation } from "effection";

export const files = createApi("files", {
  *readFile(path: string): Operation<string> {
    throw new Error(`readFile("${path}") is not implemented`);
  },
});

export const { readFile } = files.operations;

在您的运行时间设置中, 通过 min数字 :

import { files } from "./files.ts";

function* initNodeRuntime() {
  yield* files.around(
    {
      *readFile([path], _next) {
        return yield* nodeReadFile(path);
      },
    },
    { at: "min" },
  );
}

max 中间器件照常包在外头 min 实值 提供实际执行情况:

import { files } from "./files.ts";

function* withLogging() {
  yield* files.around({
    *readFile([path], next) {
      console.log(`reading ${path}`);
      return yield* next(path);
    },
  });
}

在测试中,通过登记不同的执行交换 min数字 :

function* useTestFixtures(fixtures: Map<string, string>) {
  yield* files.around(
    {
      *readFile([path], _next) {
        return fixtures.get(path) ?? "";
      },
    },
    { at: "min" },
  );
}

带有最大中间软件的执行命令 [M1, M2] 和中线软件 [m1, m2] 为:

M1 → M2 → m1 → m2 → core

仪器

中件可用于自动仪器:

import { fetching } from "./fetching.ts";

function* instrumentFetch(tracer) {
  yield* fetching.around({
    *fetch(args, next) {
      try {
        tracer.begin("fetch", args);
        return yield* next(...args);
      } finally {
        tracer.end("fetch", args);
      }
    },
  });
}

测试模拟

在不更改呼叫站点的情况下,在测试情况下进行模拟操作:

import { fetching } from "./fetching.ts";

function* useMocks() {
  yield* fetching.around({
    *fetch([url, ...rest], next) {
      if (url === "/my-path") {
        return new MockResponse("my-path");
      } else {
        return yield* next(url, ...rest);
      }
    },
  });
}

范围隔离

安装在子范围中的中件不影响父母:

import { scoped } from "effection";
import { log, logging } from "./logging.ts";

function* example() {
  yield* scoped(function* () {
    yield* logging.around({
      *log([...values], next) {
        // only active inside this scope
        return yield* next(...values);
      },
    });
    yield* log("intercepted"); // middleware runs
  });

  yield* log("not intercepted"); // middleware does not run
}

API 密码

createApi(name, handler)

从处理器函数的名称和对象创建上下文 API 或 操作。 返回对象与 operations 财务报告和审定财务报表 around。 。 。 .

import { createApi } from "@effectionx/context-api";
import type { Operation } from "effection";

const math = createApi("math", {
  *add(left: number, right: number): Operation<number> {
    return left + right;
  },
});

const { add } = math.operations;

function* example(): Operation<void> {
  const result = yield* add(1, 2); // => 3
}

around(middlewares, options?)

在一个或多个操作周围注册中间软件 。 第二个参数控件 优先级 :

  • { at: "max" } (默认)——最外,最接近呼叫者
  • { at: "min" } ——最内向,最接近核心处理器
function* example() {
  // Wrapping middleware (max, default)
  yield* math.around({
    *add(args, next) {
      console.log("adding", args);
      return yield* next(...args);
    },
  });

  // Implementation middleware (min)
  yield* math.around(
    {
      *add([left, right], _next) {
        return left * right; // replace the core implementation
      },
    },
    { at: "min" },
  );
}

每一个中间器件都接收到这些论点 next 函数改为 委托给下一个中件(或核心处理器). 中间软件可以:

  • 通过: 调用 next(...args) 并返回结果
  • 变换参数: 调用 next() 有不同论据
  • 转换返回值: 修改什么 next() 返回时
  • 短路: 返回一个不调用值 next() 完全没有

版本与发布记录

@effectionx/context-api 共发布 13 个版本,首次发布于 2025/08/07;过去 12 个月发布了 10 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.6.0latest2026/04/107 个月前
0.5.32026/03/307 个月前
0.5.22026/03/237 个月前
0.5.12026/03/217 个月前
0.4.02026/03/138 个月前
0.3.22026/02/248 个月前

关于 @effectionx/context-api 的常见问题

@effectionx/context-api 是什么?

具有中间软件的上下文操作的代数效应模式

如何安装 @effectionx/context-api?

在项目目录运行 npm install @effectionx/context-api,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:effection(^3 || ^4)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@effectionx/context-api 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@effectionx/context-api 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@effectionx/context-api 可以商用吗?

@effectionx/context-api 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@effectionx/context-api 的下载量有多少?

根据 npm 官方下载统计,@effectionx/context-api 在 2026/10/13 – 2026/11/11 这 30 天内被下载 59,235 次,日均约 1,975 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@effectionx/context-api 还在维护吗?

最新版本 0.6.0 发布于 2026/04/10(7 个月前);至今共发布 13 个版本,其中过去 12 个月发布了 10 个;首次发布于 2025/08/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。