Skip to content

Cancellation and Timeouts

Cancellation in @vgerbot/async is cooperative. APIs expose a handle that can be cancelled, and running tasks receive a token they can check or use to wrap async work.

import { cancellable } from "@vgerbot/async";
const handle = cancellable(async (token) => {
await token.sleep(1_000);
token.throwIfCancelled();
return "done";
});
handle.cancel("No longer needed");
  • CancellableHandle is returned to the caller.
  • CancellableToken is passed into the task.
  • CancelError represents cancellation failures.
  • timeout can automatically cancel a task after a duration.

Use token.wrap() when a task awaits work that should stop observing results after cancellation.

const handle = cancellable(async (token) => {
const response = await token.wrap(fetch("/api/profile"));
return response.json();
});

When wrapping another CancellableHandle, cancellation is forwarded to the nested handle.

token.sleep() creates a cancellable delay. token.throwIfCancelled() is useful after expensive work or before committing results.

const handle = cancellable(async (token) => {
await token.sleep(500);
token.throwIfCancelled();
return "ready";
});

Pass timeout to cancel a task automatically.

const handle = cancellable(
async (token) => {
await token.sleep(5_000);
return "done";
},
{ name: "slow-task", timeout: 1_000 },
);

queue.cancel() rejects pending work and cancels the shared token observed by running workers.

const uploads = queue(uploadFile, { concurrency: 2 });
uploads.push(file);
uploads.cancel("Route changed");

Executor cancel() permanently disables that executor. Some executors also support selective cancellation by task kind.

const executor = new PoolTaskExecutor(2);
executor.exec(loadUser, { kind: "user" });
executor.cancel({ kind: "user", reason: "Refresh requested" });
  • auto propagates cancellation through dependency tasks.
  • queue exposes queue-level cancellation.
  • PoolTaskExecutor documents executor cancellation behavior.