Search documentation

Search all pages, headings and text, in the current package or topic or in all documentation.

Async work

Operations with a policy, typed outcomes and cancellation, so a late answer can never overwrite newer state.

@workspace/active-state 1.0.1Developmentunreleased, in development in Foundationbaseline ce081dc3

An Operation owns work that takes time: a request, a computation, anything that resolves later. It decides what happens when a new call arrives while one is running, and it only lets a call change state through ctx.commit, so a call that lost its turn cannot write.

A search that a late answer cannot overwriteClient

0 found

    Policies#

    PolicyA new call while one runs
    latest-winssupersedes the running call; its signal aborts and it cannot commit
    drop-while-runningis dropped: it ends cancelled('dropped') at once
    queuewaits; calls run one at a time, in order

    Committing state#

    TypeScript
    import {Operation, Scope, Store} from '@workspace/active-state';
    const scope = new Scope();const results = new Store<string[]>([]);
    const search = new Operation<string, string[]>({  scope,  policy: 'latest-wins',  run: async (query, ctx) => {    const response = await fetch(`/api/search?q=${query}`, {      signal: ctx.signal,    });    const found = (await response.json()) as string[];    ctx.commit(() => results.setState(found)); // refused once superseded    return found;  },});

    ctx.commit runs its callback as a transaction, and only while the call still has authority. A direct write after an await is not protected: always write through ctx.commit.

    Outcomes, not exceptions#

    invoke() returns an Invocation with an id, a status and an outcome promise that never rejects:

    outcome.statusMeaning
    succeededvalue is the result of run
    failederror is what run threw or rejected with
    supersededby is the id of the call that replaced it
    cancelledreason: requested, owner-disposed, dropped or transaction-reverted

    operation.status is a source of {phase, running, queued, last}; read it with useStore to show a busy state.

    Ending the work#

    Disposing the Scope (or the operation) cancels every call with owner-disposed and aborts their signals. A component that owns a model for its own lifetime can use useScoped (experimental; see the API reference).

    This page as Markdown