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.