Native JS Requests
Modern browsers initially used the XMLHttpRequest object to exchange data with servers. It can send and receive data in formats like JSON, XML, HTML, and plain text.
Let's first wrap the native request:
var xmlhttp = new XMLHttpRequest();
function obj2str(data) {
data = data || {}; // If no parameter is passed, create an object to add a random factor
data.t = new Date().getTime();
var res = [];
for (var key in data) {
// Chinese characters must be encoded in URLs
res.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
}
return res.join("&");
}
function ajax(option) {
var str = obj2str(option.data); // key=value&key=value
var xmlhttp, timer;
if (option.type.toLowerCase() === "get") {
xmlhttp.open(option.type, option.url + "?" + str, true);
xmlhttp.send();
} else {
xmlhttp.open(option.type, option.url, true);
// Note: The following code must be placed between open and send
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(str);
}
xmlhttp.onreadystatechange = function (ev2) {
if (xmlhttp.readyState === 4) {
clearInterval(timer);
// Check if the request succeeded (HTTP status >= 200 and < 300, or 304)
if ((xmlhttp.status >= 200 && xmlhttp.status < 300) || xmlhttp.status === 304) {
option.success(xmlhttp);
} else {
option.error(xmlhttp);
}
}
};
if (option.timeout) {
timer = setInterval(function () {
console.log("Aborting request");
xmlhttp.abort();
clearInterval(timer);
}, option.timeout);
}
}
Usage:
ajax({
url: "http://server-name/login",
type: 'post',
data: {
username: 'username',
password: 'password'
},
dataType: 'json',
timeout: 10000,
contentType: "application/json",
success: function(data) {
// Handle server response
},
error: function(e) {
console.log(e);
}
});
Advantages:
- Update a web page without reloading it
- Request/receive data from a server after the page has loaded
- Send data to a server in the background
Disadvantages:
- Cumbersome to use, requiring many settings
- Early IE had its own implementation, requiring compatibility code
jQuery Ajax
To manipulate the DOM more quickly and avoid some browser compatibility issues, jQuery was created. Its AJAX requests are compatible with various browsers and offer simple methods like $.get and $.post. Essentially, it is a wrapper around XMLHttpRequest.
$.ajax({
type: 'POST',
url: url,
data: data,
dataType: dataType,
success: function () {},
error: function () {}
});
Advantages:
- Wraps native
XHRwith compatibility handling, simplifying usage - Adds support for
JSONPto handle some cross-origin requests
Disadvantages:
- Multiple requests with dependencies can lead to callback hell
- Designed for MVC, which is out of sync with modern MVVM frameworks
- Ajax is just one method in jQuery; using it requires importign the entire jQuery library, which is inefficient
Axios
Axios is a Promise-based HTTP library that can be used in browsers and node.js. It wraps XMLHttpRequest but implements it with Promises, aligning with the latest ES standards.
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'liu',
lastName: 'weiqin'
}
})
.then(res => console.log(res))
.catch(err => console.log(err));
Advantages:
- Creates
XMLHttpRequestsfrom the browser - Creates
httprequests fromnode.js - Suppports
PromiseAPI - Intercepts requests and responses
- Transforms request and response data
- Cancels requests
- Automatically transforms
JSONdata - Client-side support for protecting against
XSRF
Disadvantages:
- Only supports modern browsers
Fetch
The Fetch API provides a JavaScript interface for accessing and manipulating parts of the HTTP pipeline, such as requests and responses. It also provides a global fetch() method that offers a simple and reasonable way to fetch resources asynchronous across the network.
Fetch is a low-level API intended to replace XHR. It can easily handle various formats, including non-textual ones, and can be used by other technologies like Service Workers. However, using fetch effectively requires some wrapping.
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
Current issues with fetch:
Fetchonly rejects promises on network errors; HTTP errors like 400 or 500 still resolve, requiring additional handlingFetchdoes not send cookies by default; thecredentialsoption must be setFetchdoes not supportabortor timeout control natively; usingsetTimeoutandPromise.rejectfor timeout control does not stop the request from continuing in the background, wasting bandwidthFetchcannot natively monitor request progress, unlikeXHR
Note the two main differences between the fetch specification and jQuery.ajax():
- When receiving an HTTP status code that represents an error (like 404 or 500), the Promise returned from fetch() is not marked as reject; instead, it resolves (with the ok property of the response set to false). Only network failures or request blocking cause a reject.
- By default, fetch does not send or receive any cookies from the server. If the site relies on user sessions, this will result in unauthenticated requests (the credentials option must be set to send cookies).