























This post explains a hidden gem in the XMLHttpRequest standard that simplifies the process of fetching and parsing JSON data through Ajax.
A common way to offer server-generated data to browsers so that it can be used in client-side JavaScript is by formatting the data as JSON, and making it accessible through its own URL. For example:
$ curl 'https://mathiasbynens.be/demo/ip'
{"ip":"173.194.65.100"}
To make it easy to use this data in client-side JavaScript, most API endpoints offer a JSON-P version too:
$ curl 'https://mathiasbynens.be/demo/ip?callback=foo'
foo({"ip":"173.194.65.100"})
JSON-P allows you to use JSON-formatted data directly in JavaScript without having to programmatically parse it first. In other words, JSON-P is valid JavaScript, which allows you to do:
<script>
window.hollaback = function(data) {
alert('Your public IP address is: ' + data.ip);
};
</script>
<script src="https://mathiasbynens.be/demo/ip?callback=hollaback"></script>
Some APIs don’t offer JSON-P, though, and in some situations it’s preferable to load the raw JSON data through Ajax, then parse the serialized data string using JSON.parse() (or its polyfill for older browsers). This can be done as follows:
var getJSON = function(url, successHandler, errorHandler) {
var xhr = typeof XMLHttpRequest != 'undefined'
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('get', url, true);
xhr.onreadystatechange = function() {
var status;
var data;
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
if (xhr.readyState == 4) { // `DONE`
status = xhr.status;
if (status == 200) {
data = JSON.parse(xhr.responseText);
successHandler && successHandler(data);
} else {
errorHandler && errorHandler(status);
}
}
};
xhr.send();
};
getJSON('https://mathiasbynens.be/demo/ip', function(data) {
alert('Your public IP address is: ' + data.ip);
}, function(status) {
alert('Something went wrong.');
});
The above code works in pretty much any relevant browser, including IE6.
So far, I probably haven’t told you anything you didn’t already know. But here comes the good part. Thanks to a ‘hidden’ (not widely known) gem in the XMLHttpRequest standard, this code can be simplified a bit!
xhr.responseType = 'json'Each XMLHttpRequest instance has a responseType property which can be set to indicate the expected response type. When the property is set to the string 'json', browsers that support this feature automatically handle the JSON.parse() step for you. Using this feature, the above example can be written more elegantly:
var getJSON = function(url, successHandler, errorHandler) {
var xhr = typeof XMLHttpRequest != 'undefined'
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onreadystatechange = function() {
var status;
var data;
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
if (xhr.readyState == 4) { // `DONE`
status = xhr.status;
if (status == 200) {
successHandler && successHandler(xhr.response);
} else {
errorHandler && errorHandler(status);
}
}
};
xhr.send();
};
getJSON('https://mathiasbynens.be/demo/ip', function(data) {
alert('Your public IP address is: ' + data.ip);
}, function(status) {
alert('Something went wrong.');
});
Check out the demo. Note that when the responseType is set to 'json', xhr.response must be used instead of xhr.responseText. When the browser fails to parse the response as JSON, null is returned (instead of throwing an error).
Since this code only works in modern browsers with xhr.responseType = 'json' support anyway, we might as well get rid of the code paths for legacy browsers:
var getJSON = function(url, successHandler, errorHandler) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
successHandler && successHandler(xhr.response);
} else {
errorHandler && errorHandler(status);
}
};
xhr.send();
};
getJSON('https://mathiasbynens.be/demo/ip', function(data) {
alert('Your public IP address is: ' + data.ip);
}, function(status) {
alert('Something went wrong.');
});
Much better, no? This is what the future looks like :) It gets even better when combined with JavaScript promises:
var getJSON = function(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
resolve(xhr.response);
} else {
reject(status);
}
};
xhr.send();
});
};
getJSON('https://mathiasbynens.be/demo/ip').then(function(data) {
alert('Your public IP address is: ' + data.ip);
}, function(status) {
alert('Something went wrong.');
});
xhr.responseType = 'json' has only been in the spec since December 2011, and as of March 2016, Firefox ≥ 10 (Gecko), Chrome/Chromium ≥ 31, Opera (even the old Presto-based Opera 12!), Microsoft Edge, and Safari/WebKit all support it.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。