fetch
fetch is a global, so you call it with no import. It's the WHATWG Fetch API,
narrowed to what a device delivers.
On firmware, HTTPS certificate validation also needs the correct UTC date and time.
A new board can start near 1970 even after Wi-Fi connects. Set its clock before
HTTPS requests; on the Waveshare boards, clock.setTime() also provisions the
battery-backed RTC. A successful Wi-Fi connection alone does not synchronize time.
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 cancels the underlying
request itself, 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
}
}
Kog always rejects an aborted fetch with an AbortError, even for
AbortSignal.timeout(ms). A browser rejects with a TimeoutError there, so
browser code that checks err.name === 'TimeoutError' should check for
AbortError on Kog.
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 the browser's
same-origin policy, not a Kog limitation.
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.