XMLHttpRequest (XHR) began at Microsoft as the engine of Outlook Web Access for Exchange 2000. It is Baseline Widely available (since January 2018), but prefer fetch(); XHR survives in legacy code and for upload progress (xhr.upload.onprogress), which Fetch lacks. Never pass false to open() for a synchronous request: it freezes the page. Call open(), then send() a body such as new FormData(form); readyState 4 means done.
<pre id="log" style="font: 15px monospace"></pre>
<script>
const log = (msg) => (document.getElementById('log').textContent += msg + '\n');
const data = new Blob(['{"city":"Kuching","temp":31}'], { type: 'application/json' });
const xhr = new XMLHttpRequest();
xhr.open('GET', URL.createObjectURL(data)); // asynchronous by default
xhr.responseType = 'json'; // parse the body for us
xhr.onreadystatechange = () => log(`readyState ${xhr.readyState}`);
xhr.onprogress = (e) => log(`progress ${e.loaded} of ${e.total} bytes`);
xhr.onload = () => log(`status ${xhr.status}: ${xhr.response.city} is ${xhr.response.temp} °C`);
xhr.send();
</script>