JavaScript Ajax Fetch ================================================== (2018) (See also https://paulgorman.org/technical/api-design.txt.html .) The Fetch API simplifies AJAX calls compared to the old XMLHttpRequest, without resorting to jQuery. The `fetch()` method takes one mandatory argument, the resource to fetch. It returns a promise that resolves to the response from that request (successful or not). The `fetch()` method accepts a second, optional argument to initialize the Request. The Fetch API makes use of JavaScript promises (introduced in ECMAScript 6). A promise simplifies an asynchronous operation by acting as a placeholder. Any given promise exists in one of three possible states: - pending, when the asynchronous operation has not yet produced its result - fulfilled, after completion of the operation has returned a value - rejected, gives a reason for the final failure of an operation Promises also facilitate error handling in a manner similar to `try/catch` but with `then`. `then` takes one or two arguments: a callback for success, and a second for failure. Chain `then`s together to transform values (by returning a value) or run a series of additional asynchronous actions (by returning a promise). If a `then` explicitly returns a value, that value will be available for a subsequent chained `then`. ``` fetch('/api/v1/hello') .then( function(response) { response.text() .then( function(text) { console.log(text); }, function(error) { console.log('Failed to extract text from hello response', error); } ) }, function(error) { console.log('Failed to fetch hello', error); } ) ``` `catch` is roughly equivalent to the above. A subtle distinction is that, when calling `then` with two functions as arguments, only one will be called; with `catch`, both the `then` function and the `catch` function get called following a rejection. ``` fetch('/api/v1/hello') .then( function(response) { response.text() .then( function(text) { console.log(text); } ) .catch( function(error) { console.log('Failed to extract text from hello response', error); } ) } ) .catch( function(error) { console.log('Failed to fetch hello', error); } ) ``` Or, slightly more concisely: ``` fetch('/api/v1/hello') .then( function(response) { return response.text(); } ) .then( function(text) { console.log(text); } ) .catch( function(err) { console.log(err); } ) ``` Even more concisely using arrow functions: ``` fetch('/api/v1/hello') .then(response => response.text()) .then(text => console.log(text)) .catch(err => console.log(err)); ``` The response returned by `fetch()` is not itself JSON, but a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#response_objects) object providing the methods: `clone()`, `redirect()`, `arrayBuffer()`, `formData()`, `blog()`, `text()`, and `json()`. Call `text()` on the response to get the data as a text value, for example. The response object also has the `Response.ok` and `Response.status`. `Response.ok` is true of the HTTP response code is in the range 200–299. `Response.status` contains the specific numeric HTTP response code. It's possible to construct the Request we send by suppling an `init` object as a second optional arugument to `fetch()`. This can set the method (e.g., GET or POST), credentials (cookies), headers, and so forth. ``` var request = new Request('/api/v1/foo', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }); fetch(request).then(function() { /* Handle the response. */ }); ``` Links -------------------------------------------------- - https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch - https://spring.io/understanding/javascript-promises - https://developers.google.com/web/fundamentals/primers/promises - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then - https://developers.google.com/web/fundamentals/primers/promises - https://davidwalsh.name/fetch - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises