Skip to the content

Context timeline

Six scenarios that read a variable at the points of risk, with the library and with a global variable.

How to read the timeline

Select a scenario. The page starts the scenario with the library and records each read of the variable. Each lane is one task. Each dot is one read, in the order of the reads. The fill color is the context that the read got:

  • A ring of normal width marks a read that got the expected context.
  • A thick yellow ring marks a read that got the root context. The value was lost.
  • A thick red ring marks a read that got the context of a different task.

Point to a dot to look at the read. The tip shows the place in the code, the expected context and the context that the read got. Each chart also has a table of the reads.

Compare with a global variable

Select a global variable in the "Compare" list to start the same scenario with it:

  • Global variable, set back. run() sets the value, and sets the previous value again when fn gives its result. After the first await, the value is gone.
  • Global variable, not set back. run() sets the value and does not set it back. Code gets the value of the last run(), also from a different task. The old runtime of this library had this problem after each await.

Rule C3

Task B starts first, so it continues before task A after each microtask. Task A reads the variable in the same expression as an await, in call arguments and in an if block. A runtime that sets the context only at the start of the next statement gives B to these reads.

const taskB = variable.run("B", async () => {
    for (let step = 1; step <= 3; step++) {
        await null;
        record("B");
    }
});
const taskA = variable.run("A", async () => {
    const row = { first : await null, id : record("A") };
    const sum = add(await Promise.resolve(1), record("A").length);
    if (await true) record("A");
});
await Promise.all([taskA, taskB]);

async-browser-context

The real Variable class of the library, in this page. The Vite plugin of the library transforms the code of the scenarios.

  • 6 reads
  • 6 correct
  • 0 lost
  • 0 wrong

await in an expression: the reads with async-browser-context

AB123456Order of the reads →BABABA
Show the data as a table
OrderTaskPlace in the codeExpectedGotResult
1BAfter await number 1BBcorrect
2AIn an object literal, after awaitAAcorrect
3BAfter await number 2BBcorrect
4AIn the arguments of a function, after awaitAAcorrect
5BAfter await number 3BBcorrect
6AIn an if block, after awaitAAcorrect

Global variable, not set back

One global value. run() sets the value and does not set it back. Code gets the value of the last run(), also from a different operation.

  • 6 reads
  • 3 correct
  • 0 lost
  • 3 wrong

await in an expression: the reads with Global variable, not set back

AB123456Order of the reads →AAAAAA
Show the data as a table
OrderTaskPlace in the codeExpectedGotResult
1BAfter await number 1BAwrong context
2AIn an object literal, after awaitAAcorrect
3BAfter await number 2BAwrong context
4AIn the arguments of a function, after awaitAAcorrect
5BAfter await number 3BAwrong context
6AIn an if block, after awaitAAcorrect
  • Context A
  • Context B
  • Context C
  • Root context (no value)
  • Lost
  • Wrong context

The scenarios

ScenarioRuleWhat to look for
await in an expressionC3Task B continues first after each microtask. Each read of task A must still get A.
A cached promiseC4Two requests and the root context use then() on one promise. Each callback gets the context of its then() use.
Timers and microtasksC6Each callback gets the context of the code that scheduled it.
A click eventC13A click from the root context gives the registration context. A click from context C gives C.
A generatorC5The body of the generator gets the context of its creation.
An untransformed dependencyC7The callback after a native await gets the root context, not the context of request B.

async-browser-context: AsyncLocalStorage and the TC39 AsyncContext API for browsers. The source code is on GitHub.

To change a page, edit its file in site/content/. The writing style guide tells you how.

An AI model (Claude, from Anthropic) wrote most of the text and the code of this site and of the library, under the direction of the author. The tests and the STE linter examine them.