fetch make you wait twice?
const response = await fetch('/api/data');
const data = await response.json();
Why the second one?
We already have our response
Right?
const data = await response.json();
const data = JSON.parse(myJsonString);
.text()
const data = await response.text();
.blob()
const data = await response.blob();
const response = await fetch("/pokemon");
const text = await response.text();
const json = await response.json();
const blob = await response.blob();
const response = await fetch("/pokemon");
console.log(response);
ok: true
status: 200
statusText: ""
headers: Headers {}
url: "/pokemon"
type: "basic"
redirected: false
body: ReadableStream
bodyUsed: false
Credit: juancajuarez - stock.adobe.com
Credit: Komarov Andrey - Fotolia
const response = await fetch("/pokemon");
GET /pokemon HTTP/1.1
Host: fetch-server.truls.dev
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 214016
[{
"id": 1,
"name": {
"english": "Bulbasaur",
"japanese": "フシギダネ"
},
"type": ["Grass", "Poison"],
...
... much more data ...
fetch returns as soon as headers have
arrived
The body could still be on its way
import express from "express";
import path from "path";
import fs from "node:fs";
const app = express();
const port = 3000;
app.get("/", (req, res) => {
res.status(200);
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Content-Type", "application/json");
// 209 KB
const filePath = path.join(__dirname, "pokemon.json");
const stream = fs.createReadStream(filePath, { encoding: "utf8" });
stream.on("readable", () => {
const intervalId = setInterval(() => {
const chunk = stream.read(1);
if (chunk !== null) {
res.write(chunk);
} else {
clearInterval(intervalId);
res.end();
}
}, 5); // 1 byte every 5 ms = 0.2KB/s
});
});
pokemon.json
const response = await fetch("/pokemon");
const data = await response.json();
Time taken: 0s
That's $17.5$ minutes!
response.body is a
ReadableStream
This means we can consume the data as it reaches us
const response = await fetch("/pokemon");
const decoder = new TextDecoder("utf-8");
let data = "";
for await (const chunk of response.body) {
data += decoder.decode(chunk);
}
Time taken: 0s
Both methods will finish after 17-ish minutes
But the user is getting content for one of them!
The regular way is fine for most things
Consider streaming if you have:
Slides on github:
github.com/trulshj/presentation