One of the best kept secrets about Ajax is that its underlying API, XMLHttpRequest, is a terrible way to make Ajax requests. We’ve done a good job of creating some elegant APIS for XHR, but we can do better, and what makes us better is to use the FETCH API! Let’s take a quick look at the new window.fetch method, which is now available on Firefox and Chrome Canary. (Note: It is now available on the latest stable version of Chrome.)
XMLHttpRequest
XHR seems a little complicated to me, and I kind of want to make a joke about why XML is uppercase, but Http is lowercase?? Anyway, this is how you write XHR now:
//XHR...
if(window.XMLHttpRequest){
//Mozilla,Safari...
request = new XMLHttpRequest();
}else if(window.ActiveXObject){
/ / IE
try{
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(e){
try{
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch(e){}
}
}
// Open, send
request.open('GET'.'https://davidwalsh.name/ajax-endpoint'.true);
request.send(null);
Copy the code
Of course our JS framework makes the way we use XHR much more elegant, but as you can see from the examples above, XHR is a mess.
Basic Fetch usage
The fetch method is now provided in the global window scope, and the first argument is a URL:
// Url arguments are required, while options are optional
fetch('https://davidwalsh.name/some/url', {
method: 'get'
}).then(function(response) {
}).catch(function(err) {
// Error :(
});
Copy the code
Much like the latest Battery API, the FETCH API uses Promises to handle results or callbacks:
// Simple response processing
fetch('https://davidwalsh.name/some/url').then(function(response) {
}).catch(function(err) {
// Error :(
});
// Hang more advanced processing logic
fetch('https://davidwalsh.name/some/url').then(function(response) {
return / /...
}).then(function(returnedValue) {
// ...
}).catch(function(err) {
// Error :(
});
Copy the code
If you’re not used to using then, you might as well get used to it… It will soon be everywhere
Request header
Being able to set the request header is important for request flexibility. You can use new Headers() to create a request header
// Create an empty request header instance
var headers = new Headers();
// Add some header fields
headers.append('Content-Type'.'text/plain');
headers.append('X-My-Custom-Header'.'CustomValue');
// Check, get, and set the header fields
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type'.'application/json');
// Delete a header field
headers.delete('X-My-Custom-Header');
// Add initialization information
var headers = new Headers({
'Content-Type': 'text/plain'.'X-My-Custom-Header': 'CustomValue'
});
Copy the code
You can change the request header using the append, HAS, GET,set, and DELETE methods. This header can be used by creating a request instance.
var request = new Request('https://davidwalsh.name/some-url', {
headers: new Headers({
'Content-Type': 'text/plain'})}); fetch(request).then(function() { /* Process the response */ });
Copy the code
Let’s see what Request and Response do!
Request
A Request instance represents a fragment of a FETCH method call. You can create an advanced, customized Request by handing fetch a Request object:
- method – GET, POST, PUT, DELETE, HEAD
- Url – The requested URL
- Headers – and
Headers
The object on - Referrer – The requested referrer
- Mode-cors, no-cors, and same-origin modes
- Credentials – Sets whether cookies are sent with the request, and of course, with the same origin policy
- redirect – follow, error, manual
- Integrity-sri value
- Cache-cache mode (default, reload, no-cache)
A simple Request would look something like this:
var request = new Request('https://davidwalsh.name/users.json', {
method: 'POST'.mode: 'cors'.redirect: 'follow'.headers: new Headers({
'Content-Type': 'text/plain'})});// Now use it!
fetch(request).then(function() { /* Process the response */ });
Copy the code
Only the first parameter, URL, is required. All properties become read-only after the Request instance is created. Note that Request has a clone method, which is important when using fetch in the Service Worker API. Because a Request is a stream, it must be cloned when another fetch is called.
The fetch method is used to behave just like Request, so you can do this:
fetch('https://davidwalsh.name/users.json', {
method: 'POST'.mode: 'cors'.redirect: 'follow'.headers: new Headers({
'Content-Type': 'text/plain'
})
}).then(function() { /* Process the response */ });
Copy the code
In a Service Worker, you will probably only use Request instances, since Request and fetch are used the same way.
Response
Fetch’s then method provides an instance of Response, but you can manually create a Response object — a situation you might encounter when using Service Workers. You can set Response like this:
- type – basic, cors
- url
- Usefinalurl-boolean Specifies the value
url
Is it the last URL - Status – Status code (e.g. 200, 404…)
- Ok-boolean value, whether the response was successful (status between 200 and 299)
- StatusText – A literal description of the status code (e.g., OK)
- Headers – The headers object associated with response
Create your own response to test the Service worker
// new Response(BODY, OPTIONS)
var response = new Response('... ', {
ok: false.status: 404.url: '/'
});
// Fetch's then method takes an instance of Response
fetch('https://davidwalsh.name/')
.then(function(responseObj) {
console.log('status: ', responseObj.status);
});
Copy the code
The Response object also provides these methods:
- Clone () – Creates a copy of the Response object
- Error () – Returns a new Response object about a network error
- Redirect () – Create a new response with a different URL
- ArrayBuffer () – Returns a Promise with an arrayBuffer
resolve
- Blob () – Returns a promise that carries the BLOB
resolve
- FormData () – Returns a promise that carries the formData object
resolve
- Json () – Returns a Promise object, one that carries JSON
resolve
- Text () – Returns a return promise object, a carry
USVString
(text)resolve
Processing JSON
When you create a request that asks for JSON, the callback it gets will have JSON methods that convert the raw data into JavaScript objects
fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) {
// Convert to JSON
return response.json();
}).then(function(j) {
// Yes,j is a JavaScript object
console.log(j);
});
Copy the code
Of course, this is a simple JSON.parse(jsonString), but using the JSON method is a convenient shortcut.
Handles basic text /HTML responses
JSON will not always be the desired response format, so here you can see how to handle text or HTML responses.
fetch('/next/page')
.then(function(response) {
return response.text();
}).then(function(text) {
/ /
console.log(text);
});
Copy the code
You can get the response text by linking the Promise’s then method after the text() method.
Process Blob responses
If you want to load an image via fetch, it will be a little different, for example:
fetch('https://davidwalsh.name/flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(imageBlob) {
document.querySelector('img').src = URL.createObjectURL(imageBlob);
});
Copy the code
The Blob() method of the Response takes a Response stream and finishes reading it.
Send the From the Data
Another common case where AJAX is used is sending From Data. Here’s how to use the fetch method to send From Data:
fetch('https://davidwalsh.name/submit-json', {
method: 'post'.body: JSON.stringify({
email: document.getElementById('email').value,
answer: document.getElementById('answer').value
})
});
Copy the code
Very simple, very pleasing to the eye!
Unwritten little story
Fetch is probably a better API, but the API does not currently support cancellation requests, which would disappoint many developers.
It seems that using the new FETCH API is smarter and simpler than using XHR, and thanks to it we can implement AJAX more correctly. Fetch has the benefit of hindsight and although FETCH is not yet widely supported, I can’t wait!
This is an introduction to FETCH. For more information please go to Introduction to Fetch. If you’re looking for a Polyfill solution, check out GitHub’s Implementation.
Original link: DavidWalsh.name /fetch