Skip to main content

fetch

fetch is a global — call it with no import. It's the WHATWG Fetch API, narrowed to what a device delivers.

const res = await fetch('https://api.example.com/status');
const status = await res.json();

Reading JSON

fetch resolves as soon as the response headers arrive; the body streams in after. Call .json() (or .text(), .arrayBuffer(), .bytes()) to read it — each returns a promise and can be used once.

Try it live — this fetches a real user from a public (CORS-enabled) API and renders the name. Edit the code and it recompiles instantly:

(In the web playground this uses the browser's fetch, so it's subject to CORS — see below. On a device there's no CORS.)

A non-2xx status is not an error

Like the browser, a 404 or 500 resolves — it does not reject. Check response.ok (or response.status) yourself; a rejection means the request never completed (DNS failure, connection refused, timeout).

const res = await fetch(url);
if (!res.ok) {
throw new Error(`Request failed: ${res.status} ${res.statusText}`);
}
const data = await res.json();

POST with a JSON body

const res = await fetch('https://api.example.com/items', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ name: 'sensor-1', value: 42 }),
});

Bodies can be a string, an ArrayBuffer, a typed array, or URLSearchParams (which sets the form content-type for you). There's no FormData or Blob — use ArrayBuffer for binary uploads.

Timeouts and cancellation

There's no timeout option — use an AbortSignal, exactly as on the web. AbortSignal.timeout(ms) is the idiomatic form; aborting truly cancels the underlying request, so a device doesn't leak a socket.

try {
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
const data = await res.json();
} catch (err) {
if (err instanceof DOMException && err.name === 'AbortError') {
// timed out
}
}

To cancel manually, use an AbortController:

const controller = new AbortController();
fetch(url, { signal: controller.signal });
// later, e.g. when the screen unmounts:
controller.abort();

CORS

In the web playground, fetch is the browser's own — so a cross-origin request to a server that doesn't send permissive Access-Control-Allow-Origin headers will fail, exactly as it would on any web page. This is not a Kog limitation; it's the browser's same-origin policy.

On a device (and the desktop simulator) there is no browser and no CORS — the same code reaches any host the network routes to. So a request that fails in the playground with a CORS error will succeed once flashed to a board.

When you want a playground example to work, point it at an endpoint that sends CORS headers (most public JSON APIs do).

Errors

Network failures reject with a TypeError; an aborted request rejects with an AbortError DOMException. Wrap fetch in try/catch and branch on the error:

try {
const res = await fetch(url);
if (!res.ok) return handleHttpError(res.status);
return await res.json();
} catch (err) {
// TypeError (network) or AbortError (cancelled/timed out)
return handleNetworkError(err);
}

See the API reference for the full RequestInit, Headers, Request, and Response surface, and the divergences from the web standard.