Skip to main content

Javascript Network Requests

JS info MDN Fetch

Fetch

Fetch function send GET request by default, but you can modify the options to submit POST.

let promise = fetch(url, [options]);

// Example
let response = await fetch(url);

// If http status is between 200-299
if(response.ok){
let json = await response.json();
}
else{
console.log("Error");
}
  1. Fetch returns a promise object, we can check the http status for success or failure of the request.
  2. response.ok returns true if the http status code is 200-299
  3. Once we get the response, we can decode the body using various formats.
response.json()
response.text()
response.formData()
response.blob()
response.arrayBuffer()

More from MDN

Parsing Fetched Example
function jsonInfo(data) {
const results = []; // [{ path, type, value }]
const seen = new WeakSet(); // guard against cycles
const stack = [[data, []]]; // [node, pathArray]

while (stack.length) {
const [node, path] = stack.pop();

// null is typeof 'object' but not traversable
if (node !== null && typeof node === 'object') {
if (seen.has(node)) continue;
seen.add(node);

if (Array.isArray(node)) {
// push array items with indices
for (let i = node.length - 1; i >= 0; i--) {
stack.push([node[i], path.concat(`[${i}]`)]);
}
} else {
// push object properties
const keys = Object.keys(node);
for (let i = keys.length - 1; i >= 0; i--) {
const k = keys[i];
stack.push([node[k], path.concat(k)]);
}
}
} else {
// leaf: record its path, type, and value (optional: trim long values)
results.push({
path: path.join('.').replace(/\.\[/g, '['), // pretty paths like a.b[0].c
type: node === null ? 'null' : typeof node,
value: node
});
}
}

return results;
}

(async () => {
const res = await fetch("https://microsoftedge.github.io/Demos/json-dummy-data/64KB.json");
const data = await res.json();
console.table(jsonInfo(data).slice(0, 20)); // preview first 20 paths
})();

Form Data

Form data object

Common Methods
formData.append(name, value)
formData.append(name, blob, fileName)
formData.set(name, value)
formData.set(name, blob, fileName)
formData.delete(name)
formData.get(name)
formData.has(name)


<form id="exampleForm">
<input type="text" name="name" value="myname">
<input type="file" name="image" value="image/*">
<input type="submit">
</form>

<script>
exampleForm.onsubmit = async(event) => {
event.preventDefault(); // refresh

let response = await fetch("API", {
method: 'POST',
body: new FormData(exampleForm);
});

let result = await response.json();

console.log(result.message);
};
</script>

Download progress (TODO: Come back to fix this)

use response.body to track download progress, ReadableStream is a special object that provides info chunk by chunk

The original JS Info example use Content-Length to get the total size, but github use gzip compressed transfer which makes the received length much longer than the transfer size.

When the server uses Content-Encoding: gzip (or br, deflate, etc.):

  • Content-Length refers to the compressed payload size on the wire.

  • But the Fetch/XHR APIs give you the decompressed stream (so you read more bytes than Content-Length indicates).

  • Or the server may omit Content-Length entirely and send with Transfer-Encoding: chunked. In that case there’s no declared total size.

So if you rely blindly on Content-Length for progress:

  • You can show wrong percentages (e.g. progress bar hits 100% while still downloading more).

  • Or you get null (no header at all), leaving you with only bytes-so-far.

Fetch: Abort

MDN Abort Signal

AbortController can be used with fetch to signal abort.

Abort Basics
let controller = new AbortController();
let signal = controllere