Execution patterns

Make interruption a feature.

New work can move ahead of older work without rebuilding a schedule. The active task still owns the exact hand-off moment.

Insert urgent work while active

Anything added during an active task lands above the remaining work. Call next() after insertion and the newest urgent task runs first.

const stack = new Stack();

stack.add(
    function ordinary() {
        console.log('ordinary');
        this.next();
    },
    function active() {
        console.log('active');
        this.add(function urgent() {
            console.log('urgent');
            this.next();
        });
        this.next();
    }
);

// active → urgent → ordinary

Gate work on readiness

Use stop when work may be queued before a resource is ready. Clearing the gate does not start work implicitly, so the readiness event stays the single explicit resume point.

const pendingWrites = new Stack();
pendingWrites.stop = true;

pendingWrites.add(sendNewestDraft, sendOlderDraft);

connection.addEventListener('open', () => {
    pendingWrites.stop = false;
    pendingWrites.next();
});

A task can also set this.stop = true before calling this.next(). That hand-off consumes nothing, makes the runner idle, and preserves lower work.

Hand off after asynchronous work

easy-stack does not inspect promises. Keep the flow explicit by calling next() in the success path that should release the following task.

stack.add(function requestNewest() {
    fetch('/resource')
        .then(handleResponse)
        .then(() => this.next())
        .catch((error) => {
            this.stop = true;
            report(error);
        });
});
A returned promise is not a hand-off.

The runner deliberately ignores callback return values. Call next() only after the asynchronous condition that should release lower work.

Recover after synchronous errors

A thrown task error is rethrown to the caller and running returns to false. Pending lower work stays available for a policy decision.

try {
    stack.next();
} catch (error) {
    log(error);

    // Decide deliberately whether to continue.
    if (canRecover(error)) {
        stack.next();
    } else {
        stack.clear();
    }
}
Next pageBrowser use