API reference
Every public class, method, and event in @codexo/exojs. Generated from source.
classCoroutineSystem
Advances generator-based coroutines a step at a time in the frame's leftover capacity, so heavy work (world generation, batch pathfinding, visibility rebuilds) spreads over frames without an `async` update. It runs in the SystemMethods.postFrame phase, after the backend has flushed: the work overlaps the GPU drawing the frame just submitted, and the frame's remaining time is known rather than guessed. `app.coroutines` is the instance the application owns, and `scene.coroutines` a scene-bound facade over it. Each coroutine is stepped at most once per frame, and the first step of a frame happens whatever the budget says, so a coroutine whose single step always overruns still makes progress. That one rule is what lets a body that ignores `budget` behave like a sequence (one `yield` is one frame) while a body that consults it fills whatever the frame has left. ```ts const terrain = scene.coroutines.queue(buildWorld(map), { name: 'terrain' }); terrain.done.then(world => { scene.root.addChild(world); }); ``` The engine cannot interrupt a running step - JavaScript is run-to-completion - so a body chooses its own granularity. A step that overruns its slice by a wide margin is reported in development, naming the coroutine.
import { CoroutineSystem } from '@codexo/exojs'Advances generator-based coroutines a step at a time in the frame's leftover capacity, so heavy work (world generation, batch pathfinding, visibility rebuilds) spreads over frames without an `async` update.
It runs in the SystemMethods.postFrame phase, after the backend has flushed: the work overlaps the GPU drawing the frame just submitted, and the frame's remaining time is known rather than guessed. `app.coroutines` is the instance the application owns, and `scene.coroutines` a scene-bound facade over it.
Each coroutine is stepped at most once per frame, and the first step of a frame happens whatever the budget says, so a coroutine whose single step always overruns still makes progress. That one rule is what lets a body that ignores `budget` behave like a sequence (one `yield` is one frame) while a body that consults it fills whatever the frame has left.
```ts const terrain = scene.coroutines.queue(buildWorld(map), { name: 'terrain' });
terrain.done.then(world => { scene.root.addChild(world); }); ```
The engine cannot interrupt a running step - JavaScript is run-to-completion - so a body chooses its own granularity. A step that overruns its slice by a wide margin is reported in development, naming the coroutine.
new(options: CoroutineSystemOptions): CoroutineSystemclear(): voiddestroy(): voidpostFrame(_delta: SecondsA length of time in seconds. The unit every duration in the public API is expressed in - frame deltas, the fixed step, elapsed totals, timer limits. It is a `n…, budget: FrameBudgetHow much of the running frame is still unspent, handed to the SystemMethods.postFrame phase. Modelled on the platform's `IdleDeadline`, so the canonical loop i…): voidqueue(body: CoroutineBodyWork a CoroutineSystem advances one step per frame: a generator function whose every `yield` hands control back to the frame. Its return value becomes the coro…<T, P> | Iterator<P, T, undefined>, options: CoroutineOptions): CoroutineHandle for work handed to a CoroutineSystem. Poll Coroutine.status, Coroutine.progress and Coroutine.result from frame code, or await Coroutine.done from async…<T, P>budget: SecondsA length of time in seconds. The unit every duration in the public API is expressed in - frame deltas, the fixed step, elapsed totals, timer limits. It is a `n… | { max: SecondsA length of time in seconds. The unit every duration in the public API is expressed in - frame deltas, the fixed step, elapsed totals, timer limits. It is a `n…; share: number }order: numberdestroyed: booleanlastFrameMs: numberpending: number