HTML5 game publishing

A Boot Sequence That Cannot Hang: Timeouts for Every Dependency

Using the roughly eight-second init() rejection as a design rule: a dependency table, a Promise.race timeout helper, honest loading screens and tests that break things on purpose.

PlayKovo Team3 min read
Games currently available on PlayKovo. Open a title to see its current listing.

Games break when they depend on something that is not there. A script that never loads, a save that never answers, an ad that never returns: each one can stall a loading screen for good. The SDK gives you one hard number to design around: init() rejects if it has not resolved after about eight seconds. This post uses that number to build a boot sequence in which nothing outside your game can stop it from starting.

The fact to design around

The reference says that init() returns a promise that resolves to a status object, and that if it has not resolved after about 8 seconds, it rejects. The advice that follows is to wrap it in try/catch and fall back to a fully offline boot, with no ads and a local-only save, rather than stalling your loading screen. Our post on the init boot sequence shows the basic version. This post extends the idea to every dependency.

List your dependencies

Before you write code, list what your start-up needs:

DependencyIf it failsFallback
The SDK scriptwindow.PlayKovoSDK is undefinedRun without it; skip ads and cloud save
init()Rejects after about 8 secondsContinue offline
Cloud saveResult with ok: falseLocal save, or a new game
Your own assets404 or decoding failureRetry once, then show a clear error
Audio contextBlocked until the first clickCreate it after the first interaction

Only one line here is a real stop: your own assets. The rest can be skipped without ruining the game.

A boot that cannot hang

function withTimeout(promise, ms, fallbackValue) {
  return Promise.race([
    promise,
    new Promise(resolve => setTimeout(() => resolve(fallbackValue), ms)),
  ]);
}

async function boot() {
  let sdkReady = false;
  try {
    if (window.PlayKovoSDK) {
      const status = await window.PlayKovoSDK.init();
      sdkReady = !!status.ready;
    }
  } catch (e) {
    // init rejected or failed: continue offline
  }

  let save = null;
  if (sdkReady) {
    const r = await withTimeout(window.PlayKovoSDK.cloudSave.get(), 3000, { ok: false });
    if (r.ok && r.data) save = r.data;
  }
  if (!save) save = loadLocalSave();

  await loadAssets();
  startMainMenu(save, { ads: sdkReady });
}
boot();

Everything except the asset loading has a safe path. The cloud save gets its own shorter timeout, because the player should not wait eight seconds twice. The menu receives a flag saying whether ads are possible, so it can hide the rewarded button when they are not.

Keep the loading screen honest

If your game draws its own loading screen, tell the platform: call loadingStart() once it is visible and loadingFinished() once the game is interactive. The app then hides its own cover instead of showing two loaders. See loadingStart and loadingFinished. Call loadingFinished() in the fallback paths too. A game that fails over to offline mode but never reports finished leaves the cover up.

Retries: once, not forever

  • Retry an asset once, since a brief network error is common.
  • After the retry fails, show a message the player can read and a button to reload.
  • Do not loop. An endless retry is a hidden freeze.

Show something quickly

A player who sees nothing for several seconds leaves. Draw a logo or progress bar as early as you can, before large assets load. A simple, honest bar is better than a fake animation. Keep the first download small; see the limits in what goes in a ZIP.

Test by breaking things

  1. Load the game with the SDK script blocked (many browsers let you block a URL in the developer tools).
  2. Throttle the network to a slow connection.
  3. Disable the network after the page loads.
  4. Delete a non-essential asset from a test build and check the error message.
  5. Check each of these on a phone.

A game that boots under all five is hard to break in the field. The pattern fits the rules in the SDK guidelines about unavailable features never blocking play; see also designing for unavailable ads.

We use optional cookies for site analytics and site advertising. You can change your choice later. Privacy policy.