XMLHttpRequest

2022.06.20

XMLHttpRequest in JavaScript

#JavaScript#basics
use client /components/post/reExport XMLHttpRequest 2022.06.20 JavaScript ], imgUrl: , desc: , body: ( <> <ul> <li>XMLHttpRequest is a built-in browser object that allows to make HTTP requests in JavaScript</li> <li>Can operate on any data, not only in XML</li> <li>Can upload/download files, track progress and much more</li> <li><Lnk path= >Fetch</Lnk> somewhat deprecates XMLHttpRequest</li> </ul> <H>Used for</H> <ul> <li>support existing scripts with XMLHttpRequest</li> <li>support old browsers</li> <li>need something that fetch can’t do yet, e.g. to track upload progress</li> </ul> <H>Create</H> <Code block jsx>{ https://google.com }</Code> <ul> <li><code>method</code> HTTP-method. Usually </li> <li><code>URL</code> the URL to request, a string, can be URL object</li> <li><code>async</code> if explicitly set to false, then the request is synchronous, we’ll cover that a bit later</li> <li><code>user</code>, <code>password</code> login and password for basic HTTP auth (if required)</li> </ul> <Code block jsx>{ https://google.com/search ) // https://google.com/search?q=test+me%21 xhr.open( , url) xhr.send([body]) }</i> request is complete (even if HTTP status is like 400 or 500), and the response is fully downloaded</li> <li><i>{ }</i> request couldn’t be made, e.g. network down or invalid URL.</li> <li><i>{ }</i> triggers periodically while the response is being downloaded, reports how much has been downloaded.</li> <li><i>{ readystatechange }</i> old event, do not use it</li> </ul> <H>Properties</H> <ul> <li><Code>xhr.status</Code> HTTP status code (a number): 200, 404, 403 and so on, can be 0 in case of a non-HTTP failure</li> <li><Code>xhr.statusText</Code> HTTP status message: usually for 200, for 404, for 403 and so on</li> <li><Code>xhr.response</Code> server response body</li> <li><Code>xhr.responseText</Code> same, used in old scripts</li> <li><Code>xhr.responseXML</Code> used in old scripts</li> <li><Code>xhr.timeout = 10000</Code> timeout in ms, if the request does not succeed in 10s, it gets canceled and timeout event triggers</li> <li><Code>xhr.responseType = </Code> property to set the response format, get as string - (default)</li> <li><Code>xhr.responseType = </Code> get as string</li> <li><Code>xhr.responseType = </Code> get as ArrayBuffer (for binary data)</li> <li><Code>xhr.responseType = </Code> get as Blob (for binary data)</li> <li><Code>xhr.responseType = </Code> get as XML document (can use XPath and other XML methods) or HTML document (based on the MIME type of the received data)</li> <li><Code>xhr.responseType = </Code> get as JSON (parsed automatically)</li> <li><Code>xhr.readyState</Code> XMLHttpRequest changes between states as it progresses</li> <li><Code js>xhr.setRequestHeader(name, value)</Code> sets the request header with the given name and value</li> <li><Code js>xhr.getResponseHeader(name)</Code> gets the response header with the given name (except Set-Cookie and Set-Cookie2)</li> <li><Code js>xhr.getAllResponseHeaders()</Code> returns all response headers, except Set-Cookie and Set-Cookie2</li> <li><Code js>xhr.withCredentials = true</Code> send cookies and HTTP-authorization to another origin</li> </ul> <H>Examples</H> <Code block jsx>{ /article/xmlhttprequest/example/load Error \${xhr.status}: \${xhr.statusText}\ Done, got \${xhr.response.length} bytes\ Received \${event.loaded} of \${event.total} bytes\ Received \${event.loaded} bytes\ Request failed }</Code> <Code block jsx>{ /article/xmlhttprequest/example/json xhr.send() xhr.onload = function() { let responseObj = xhr.response // { Hello, world! }</Code> <H>xhr.readyState</H> <p><Code>xhr.readyState</Code> XMLHttpRequest changes between states as it progresses</p> <ul> <li><Code>xhr.readyState = 0</Code> initial state</li> <li><Code>xhr.readyState = 1</Code> open called</li> <li><Code>xhr.readyState = 2</Code> response headers received</li> <li><Code>xhr.readyState = 3</Code> response is loading (a data packet is received)</li> <li><Code>xhr.readyState = 4</Code> request complete</li> <li>We can track state using readystatechange event</li> <li>It is an old approach, do not use it</li> </ul> <Code block jsx>{ }</Code> <Code block jsx>{ , xhr.statusText); break; case 1: // OPENED, open() has been called. console.log( , xhr.statusText); break; case 2: // HEADERS_RECEIVED, send() has been called, and headers and status are available. console.log( , xhr.statusText); break; case 3: // LOADING, Downloading; responseText holds partial data. console.log( , xhr.statusText); console.log( + xhr.responseText.length + ); break; case 4: // DONE, The operation is complete. console.log( , xhr.statusText); const header = xhr.getResponseHeader( ); const headers = xhr.getAllResponseHeaders(); if (xhr.status == 200 || xhr.status == 304) { var data = xhr.responseText; console.log( ); console.dir(data); } else { console.log( + xhr.statusText); } break; } }; xhr.withCredentials = true; xhr.responseType = ; xhr.setRequestHeader( application/json ); xhr.send(null); is set to , the request is made synchronously</li> <li>JavaScript pauses at send() and resumes when the response is received</li> </ul> <Code block jsx>{ /article/xmlhttprequest/hello.txt Error \${xhr.status}: \${xhr.statusText}\ Request failed }</Code> <H>HTTP-headers</H> <Hs>setRequestHeader</Hs> <Code block jsx>{ }</Code> <ul> <li>Sets the request header with the given name and value.</li> <li>Several headers are managed exclusively by the browser, e.g. </li> <li>Once the header is set, it’s set, can not overwrite it after</li> </ul> <Code block jsx>{ Content-Type application/json }</Code> <Hs>getResponseHeader</Hs> <Code block jsx>{ }</Code> <p>Gets the response header with the given name (except Set-Cookie and Set-Cookie2).</p> <Code block jsx>{ Content-Type }</Code> <Hs>getAllResponseHeaders</Hs> <ul> <li>Returns all response headers, except Set-Cookie and Set-Cookie2</li> <li>Headers are returned as a single line</li> <li>The line break between headers is always </li> <li>we can easily split it into individual headers</li> <li>The separator between the name and the value is always a colon followed by a space </li> </ul> <Code block jsx>{ ) .reduce((result, current) => { let [name, value] = current.split( ) result[name] = value return result }, {}) // headers[ }</Code> <H>POST with FormData</H> <p>To make a POST request, we can use the built-in FormData object.</p> <Code block html>{ > <input name= > <input name= > </form> const formData = new FormData(document.forms.person) // pre-fill FormData from the form formData.append( ) // add one more field const xhr = new XMLHttpRequest() xhr.open( /article/xmlhttprequest/post/user , surname: }) xhr.open( ) xhr.setRequestHeader( application/json charset=utf-8 }</Code> <H>Upload progress</H> <ul> <li><code>xhr.upload</code> generates events and triggers them on uploading</li> <li><code>xhr.upload = </code> upload started</li> <li><code>xhr.upload = </code> triggers periodically during the upload</li> <li><code>xhr.upload = </code> upload aborted</li> <li><code>xhr.upload = </code> non-HTTP error</li> <li><code>xhr.upload = </code> upload finished successfully</li> <li><code>xhr.upload = </code> upload timed out (if timeout property is set)</li> <li><code>xhr.upload = </code> upload finished with either success or error</li> </ul> <Code block jsx>{ Uploaded \${e.loaded} of \${e.total} bytes\ Upload finished successfully.\ Error during the upload: \${xhr.status}\ }</Code> <Code block html>{ onchange= }</Code> <Code block jsx>{ Uploaded \${e.loaded} of \${e.total}\ ) } else { console.log( + this.status) } } xhr.open( /article/xmlhttprequest/post/upload }</Code> <H>Cross-origin requests</H> <ul> <li><i>XMLHttpRequest</i> can make cross-origin requests, using the same CORS policy as fetch</li> <li>Just like fetch, it doesn’t send cookies and HTTP-authorization to another origin by default</li> <li>To enable them, set xhr.withCredentials to true</li> </ul> <Code block jsx>{ http://anywhere.com/request