Cross domain request in JavaScript vs. jQuery's JSONP
I was trying to write a cross domain request (eg, Google Finance resource) in JavaScript from client-side (the browser) by following a template like below mentioned here:
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
var url = 'http://finance.google.com/finance/info?client=ig&q=NASDAQ:GOOGL';
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
var jsonReturend = JSON.parse(text);
console.log(jsonReturend)
};
xhr.onerror = function() {
alert('Woops, there was an error making the request.');
};
xhr.send();
But it doesn't work because (I think) 'finance.google.com' doesn't include Access-Control-Allow-Origin:
in its response headers, which is understandable. However, I tried another suggested method on StackOverflow post here to use JSONP as follows:
$.ajax({
url: 'http://finance.google.com/finance/info?client=ig&q=NASDAQ:GOOGL',
jsonp: "callback",
dataType: "jsonp",
data: {},
// Work with the response
success: function( response ) {
console.log( response ); // server response
}
});
and it works (that is, I got the expected JSON back)! As a newbie to web development and JS in general, I am not sure why AJAX call via jQuery's JSONP is working whereas it fails in pure JavaScript. My questions are:
Thank you all for your answers!
Cross origin XHR requests have to be allowed by the server using Access-Control-Allow-Origin
. JSONP is a mechanism to work around it.
This wiki page contains very good description of why it works. See the Script element injection section.
https://en.wikipedia.org/wiki/JSONP
This stackoverflow answer shows how to use pure javascript to make jsonp calls.
Can anyone explain what JSONP is, in layman terms?
First, I will show the response of the request here:
// [ { "id": "694653" ,"t" : "GOOGL" ,"e" : "NASDAQ" ,"l" : "796.87" ,"l_fix" : "796.87" ,"l_cur" : "796.87" ,"s": "2" ,"ltt":"4:00PM EDT" ,"lt" : "Sep 2, 4:00PM EDT" ,"lt_dts" : "2016-09-02T16:00:02Z" ,"c" : "+5.47" ,"c_fix" : "5.47" ,"cp" : "0.69" ,"cp_fix" : "0.69" ,"ccol" : "chg" ,"pcls_fix" : "791.4" ,"el": "796.01" ,"el_fix": "796.01" ,"el_cur": "796.01" ,"elt" : "Sep 2, 7:45PM EDT" ,"ec" : "-0.86" ,"ec_fix" : "-0.86" ,"ecp" : "-0.11" ,"ecp_fix" : "-0.11" ,"eccol" : "chr" ,"div" : "" ,"yld" : "" } ]
Actually, the XHR request in you javascript template works. The error happen when the script trying to parse the JSON text ( var jsonReturend = JSON.parse(text);
). It happen because the text that you will parse is not a good json text. You see the response above, it has two slashes in the beginning. JSON should not have it.
So, to make the text parseable by JSON.parse()
you need to remove those slashes. Here is the fix of your javascript block:
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
text = text.replace("// ","");// replace slashes, make it a pure JSON text
var jsonReturend = JSON.parse(text);
console.log(jsonReturend)
};
Now, JSON.parse()
will be able to parse the text.
JSONP in jquery ajax request is only an option to format the response of request. It has nothing to do with the request itself. If you set the ajax option to dataType:"jsonp"
, the script will work. And if you set it to dataType:"json"
the script will not work. The dataType
option defines how the response will be formatted.
Of course, you can use dataType:"text"
too. But you cannot directly use it as object or JSON.