Skip to content

t1k:cocos:playable:async-utilities

FieldValue
Moduleplayable
Version0.5.6
Efforthigh
Tools

Keywords: ads, async, cancellation token, cocos, playable, task, utilities

/t1k:cocos:playable:async-utilities

AsyncTask & CancellationToken — Async Utilities

Section titled “AsyncTask & CancellationToken — Async Utilities”

UniTask-inspired async helpers for Cocos Creator. All methods are static on AsyncTask. See also: t1k-cocos-playable-signalbus (for waitFor), t1k-cocos-playable-lifecycle.

Import paths:

  • db://assets/PLAGameFoundation/async/AsyncTask
  • db://assets/PLAGameFoundation/async/CancellationToken
await AsyncTask.Delay(1000); // ms
await AsyncTask.DelaySeconds(1.5); // seconds (wraps Delay)
await AsyncTask.Yield(); // next rAF frame
await AsyncTask.WaitForFrames(3); // N frames
await AsyncTask.WaitForFixedUpdate(); // ~0.02s fixed step approximation
await AsyncTask.FromSchedule(this, 0.5); // uses Cocos scheduleOnce (seconds)

Condition Polling (checked every rAF frame)

Section titled “Condition Polling (checked every rAF frame)”
await AsyncTask.WaitUntil(() => this.isReady);
await AsyncTask.WaitWhile(() => this.isLoading); // inverse of WaitUntil
// All complete (typed overload for mixed types)
await AsyncTask.WhenAll([loadA(), loadB(), loadC()]);
await AsyncTask.WhenAllTyped([loadSprite(), loadAudio()] as const);
// First wins
await AsyncTask.WhenAny([attempt1(), attempt2()]);
// Sequential — one after another, collects results
const results = await AsyncTask.Sequence([() => step1(), () => step2()]);
// Parallel with concurrency cap (default 5)
const results = await AsyncTask.Parallel([() => fetch(a), () => fetch(b)], 3);
// Attempts: 0..maxRetries. Delays: 1s, 2s, 4s, ...
const data = await AsyncTask.Retry(() => this.fetchData(), 3, 1000, cts.token);
// External resolve/reject — useful as an async gate
const deferred = AsyncTask.Deferred<boolean>();
someCallback = () => deferred.resolve(true);
const result = await deferred.promise;
const cts = new CancellationTokenSource();
// Pass token into cancellable ops
await AsyncTask.Delay(5000, cts.token);
await AsyncTask.WaitUntil(() => ready, cts.token);
await AsyncTask.Retry(() => load(), 3, 1000, cts.token);
// Cancel from anywhere
cts.cancel(); // triggers rejection in all registered ops
cts.dispose(); // same as cancel(), call when done
// Manual check inside a loop
for (const item of items) {
cts.token.throwIfCancelled(); // throws if cancelled
if (cts.token.isCancelled) break;
await process(item);
}
// Register teardown callback
cts.token.register(() => cleanupResources());

Loading gate — wait for parameters then animate in:

async onLoad() {
await AsyncTask.WaitUntil(() => PlayableConfig.isReady);
await AsyncTask.DelaySeconds(0.3);
this.playIntroAnimation();
}

Cancellable tutorial sequence:

private _cts: CancellationTokenSource;
async startTutorial() {
this._cts = new CancellationTokenSource();
try {
await AsyncTask.DelaySeconds(1, this._cts.token);
this.showHand();
await AsyncTask.DelaySeconds(2, this._cts.token);
this.hideHand();
} catch { /* cancelled */ }
}
onFirstInteraction() {
this._cts?.cancel();
}

Component-safe delay (avoids rAF after destroy):

// Prefer FromSchedule inside Cocos Components — respects component lifecycle
await AsyncTask.FromSchedule(this, 1.0);
  • Using Delay/WaitUntil inside a destroyed Component — rAF keeps running. Use FromSchedule or cancel via CancellationToken.
  • Not catching cancellation — Delay rejects with "Operation was cancelled". Wrap in try/catch.
  • WaitUntil with an expensive condition — runs every frame. Keep the lambda fast.
  • Parallel default concurrency is 5 — lower it for network-bound operations.
  • Promises survive scene unload — outstanding setTimeout/Promise callbacks fire after the scene is gone unless explicitly cancelled. Tie all timers to a CancellationToken bound to component lifecycle.
  • async/await in Cocos update() deopts — use coroutine-like primitives (Tween chains) for per-frame work.
  • Unhandled rejections silently disappear in playable runtime — wrap top-level .catch(reportToHost).