@effectionx/converge

中文文档
0.1.4发布于 2026/03/23MITTypeScriptES Module构建来源已验证近 30 天下载 4.7万

Poll and wait for conditions to be met with automatic retry and timeout

原始使用文档
文档目录11 节
  1. Why Convergence?
  2. Installation
  3. Usage
  4. when(assertion, options?)
  5. always(assertion, options?)
  6. Options
  7. Stats Object
  8. Examples
  9. Waiting for an element to appear
  10. Verifying a value remains stable
  11. Using with file system operations

@effectionx/converge

Recognize a desired state and synchronize on when that state has been achieved.

This package is a port of @bigtest/convergence adapted for Effection structured concurrency.


Why Convergence?

Let's say you want to write an assertion to verify a simple cause and effect: when a certain button is clicked, a dialog appears containing some text that gets loaded from the network.

In order to do this, you have to make sure that your assertion runs after the effect you're testing has been realized.

Image of assertion after an effect

If not, then you could end up with a false negative, or "flaky test" because you ran the assertion too early. If you'd only waited a little bit longer, then your test would have passed. So sad!

Image of false negative test

In fact, test flakiness is the reason most people shy away from writing big tests in JavaScript in the first place. It seems almost impossible to write robust tests without having visibility into the internals of your runtime so that you can manually synchronize on things like rendering and data loading. Unfortunately, those can be a moving target, and worse, they couple you to your framework.

But what if instead of trying to run our assertions at just the right time, we ran them many times until they either pass or we decide to give up?

Image of convergent assertion

This is the essence of what @effectionx/converge provides: repeatedly testing for a condition and then allowing code to run when that condition has been met.

And it isn't just for assertions either. Because it is a general mechanism for synchronizing on any observed state, it can be used to properly time test setup and teardown as well.


Installation

npm install @effectionx/converge

Usage

when(assertion, options?)

Converges when the assertion passes within the timeout period. The assertion runs repeatedly (every 10ms by default) and is considered passing when it does not throw or return false. If it never passes within the timeout, the operation throws with the last error.

import { when } from "@effectionx/converge";

// Wait for a condition to become true
let { value } = yield* when(function* () {
  if (total !== 100) throw new Error("not ready");
  return total;
});

// With custom timeout
yield* when(
  function* () {
    if (!element.isVisible) throw new Error("not visible");
  },
  { timeout: 5000 },
);

always(assertion, options?)

Converges when the assertion passes throughout the timeout period. Like when(), the assertion runs repeatedly, but it must pass consistently for the entire duration. If it fails at any point, the operation throws immediately.

import { always } from "@effectionx/converge";

// Verify a condition remains true
yield* always(function* () {
  if (counter >= 100) throw new Error("counter exceeded limit");
});

// With custom timeout
yield* always(
  function* () {
    if (!connection.isAlive) throw new Error("connection lost");
  },
  { timeout: 5000 },
);

Options

Both when and always accept an options object:

OptionTypeDefaultDescription
timeoutnumber2000 (when) / 200 (always)Maximum time to wait in milliseconds
intervalnumber10Time between assertion retries in milliseconds

Stats Object

Both functions return a ConvergeStats object with timing and execution info:

interface ConvergeStats<T> {
  start: number; // Timestamp when convergence started
  end: number; // Timestamp when convergence ended
  elapsed: number; // Milliseconds the convergence took
  runs: number; // Number of times the assertion was executed
  timeout: number; // The timeout that was configured
  interval: number; // The interval that was configured
  value: T; // The return value from the assertion
}

Example:

let stats = yield* when(
  function* () {
    return yield* fetchData();
  },
  { timeout: 5000 },
);

console.log(`Converged in ${stats.elapsed}ms after ${stats.runs} attempts`);
console.log(stats.value); // the fetched data

Examples

Waiting for an element to appear

yield* when(function* () {
  let element = document.querySelector('[data-test-id="dialog"]');
  if (!element) throw new Error("dialog not found");
  return element;
});

Verifying a value remains stable

yield* always(
  function* () {
    if (connection.status !== "connected") {
      throw new Error("connection dropped");
    }
  },
  { timeout: 1000 },
);

Using with file system operations

import { when } from "@effectionx/converge";
import { access } from "node:fs/promises";
import { until } from "effection";

// Wait for a file to exist
yield* when(
  function* () {
    let exists = yield* until(
      access(filePath).then(
        () => true,
        () => false,
      ),
    );
    if (!exists) throw new Error("file not found");
    return true;
  },
  { timeout: 10000 },
);

版本与发布记录

@effectionx/converge 共发布 5 个版本,首次发布于 2026/01/19;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.4latest2026/03/237 个月前
0.1.32026/02/248 个月前
0.1.22026/02/129 个月前
0.1.12026/01/219 个月前
0.1.02026/01/199 个月前

关于 @effectionx/converge 的常见问题

@effectionx/converge 是什么?

Poll and wait for conditions to be met with automatic retry and timeout

如何安装 @effectionx/converge?

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

@effectionx/converge 支持 TypeScript 吗?

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

@effectionx/converge 支持 ESM 还是 CommonJS?

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

@effectionx/converge 可以商用吗?

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

@effectionx/converge 的下载量有多少?

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

@effectionx/converge 还在维护吗?

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