How to use JSONP - javascript

I have the following code
function exista(word) {
alert(word);
var exists = 1;
jQuery.ajax({
async: false,
url: "http://api.wordreference.com/0.8/key/json/roen/" + word,
dataType: 'json',
method: "GET",
success: function(transport) {
if (transport.Error || transport.Response)
exists = 0;
}
});
return exists;
}
which verifies if a word exists or not in a dictionary. Problem is it gives an Access-Control-Allow-Origin error. From what I gathered it seems I must use JSONP but I can't really figure out how (sorry, I am just beginning to learn JavaScript and all that). So, got any idea on how to modify the above code?
Thank you.

Your dataType should be jsonp, not 'json`.
UPDATE
According to http://www.wordreference.com/docs/api.aspx:
Additionally, for JSPONp, the JSON API can take an optional callback
function in the query string; simply add "?callback={yourCallback}" to
the end of the URL.
so the API does support JSONP.
Additionally, JSONP means "JSON with padding", so you will get a JSON response. JSONP merely allows use of CORS.
By changing your dataType to jsonp:
"jsonp": Loads in a JSON block using JSONP. Adds an extra
"?callback=?" to the end of your URL to specify the callback. Disables
caching by appending a query string parameter, "_=[TIMESTAMP]", to the
URL unless the cache option is set to true.
You can override the default callback by specifying one with the jsonpCallback setting.
Finally, you should also add an error handler and set async to true:
jQuery.ajax({
"async": true, //cannot be false for JSONP
"url": "http://api.wordreference.com/0.8/key/json/roen/" + word,
"dataType": 'jsonp',
"method": "GET",
"error": function (jqXHR, textStatus, errorThrown) {
//included so you can see any errors
console.log(textStatus + ': ' + errorThrown);
},
"success": function (data, textStatus, jqXHR) {
//According to API documentation
//data will not likely contain either Error, or Response
//so, exists will likely not change to 0
if (data.Error || data.Response) {
exists = 0;
}
}
});
UPDATE:
The solution to both the error and the "need to be synchronous" is going to be what Pointy pointed out earlier. You'll have to create a server-side proxy that runs on the same domain as your script.
The server-side proxy can return JSONP, but frankly simply returning JSON or XML is simpler since CORS is not an issue, and the proxy can be synchronous. For a PHP example script, the Yahoo! Developer Network hosts source code for a simple proxy.
For anything else regarding a server-side web service proxy, you'd need to specify which server language you're using (and it would probably be better suited as a different question).

For JSONP to work, you not only have to code for it on your side, but the site you're targeting has to expect to be used that way as well, and respond to requests accordingly.
If the other site does not have a JSONP API already, and you have no control over it, then JSONP is not an answer. You'll have to create a server-side proxy of your own.
edit — according to the site, they do support JSONP. You just need to add "?callback=?" to the end of the URL.

Related

jQuery ignores HTTP request method and appends weird URL parameters

I have a web service that expects POST requests carrying a JSON string in the body. I'm trying to use this web service using jQuery, but I have two problems :
1) jQuery seems to always use the GET method, no matter what I do ;
2) jQuery seems to append weird things into the URL.
The relevant pice of my code :
var WEB_SERVICE_URL = 'http://localhost/XXXX/';
// ...
$.post({
url: WEB_SERVICE_URL + 'GetConfigLabels/',
contentType: 'application/json; charset=utf-8',
dataType: 'jsonp',
data: JSON.stringify(data),
processData: false,
success: function(response) {
// Whatever
},
error: function(xhr, message) {
// Whatever
}
});
The developper tools of the browser (Firefox Quantum 60.0.2) shows me a weird URL :
http://localhost/XXXX/GetConfigLabels/?callback=jQuery331012146934861340841_1530707758905&{}&_=1530707758906
While the following was expected :
http://localhost/XXXX/GetConfigLabels/
Also the HTML file is openned as a file (using file:///) through the file system, hence the use of JSONP for cross domain.
I failed to find existing questions related to this issue. What could be causing this ? Thank you !
Please refer to the dataType : json section at http://api.jquery.com/jquery.ajax/ :
"json": Evaluates the response as JSON and returns a JavaScript
object. Cross-domain "json" requests that have a callback placeholder,
e.g. ?callback=?, are performed using JSONP unless the request
includes jsonp: false in its request options. The JSON data is parsed
in a strict manner; any malformed JSON is rejected and a parse error
is thrown. As of jQuery 1.9, an empty response is also rejected; the
server should return a response of null or {} instead. (See json.org
for more information on proper JSON format
overrding random name of callback using jsonpCallback :
jsonpCallback Type: String or Function() Specify the callback function
name for a JSONP request. This value will be used instead of the
random name automatically generated by jQuery. It is preferable to let
jQuery generate a unique name as it'll make it easier to manage the
requests and provide callbacks and error handling. You may want to
specify the callback when you want to enable better browser caching of
GET requests. As of jQuery 1.5, you can also use a function for this
setting, in which case the value of jsonpCallback is set to the return
value of that function.

Returns undefined when attempting to run JQuery

$.getJSON('http://robloxplus.com:2052/inventory?username=itracking', function(data){
$.each(data, function(item){
console.log(item['id'])
});
});`
returns undefined when attempting to run it on an external website. It is supposed to output each id of every item in that list (http://robloxplus.com:2052/inventory?username=itracking)
How do I fix this?
Edits>
I want to iterate over each individual id, each of these numbers "168167114": and "135470963": etc. etc. and fetch the data that follows that (i.e. the name:"", totalSerial:"")
is the request being made on the same domain as robloxplus.com ?
I'm new to this.. I don't understand much about JavaScript and/or
JQuery. #Pedro Lobito no, it's not. –
Explanation:
HTTP requests from Javascript are traditionally bound by the Same
Origin Policy, which means that your ajax requests must have the same
domain and port. The common ways to get around this are JSON-P,
Proxying and message passing via s. These all have their
quirks, but the thing they generally have in common is legacy browser
support.
Solution
1 - If robloxplus.com is yours, you can enable CORS
2 - If not, you can use YQL (Yahoo! Query Language) to bypass CORS
When one of the above options is fulfilled, you can make your json request, i.e.:
$.ajax({
url: 'http://robloxplus.com:2052/inventory?username=itracking',
type: 'get',
dataType: 'json',
success: function(data) {
$.each(data.id, function(item) {
console.log(item);
});
},
error: function(e) {
console.log(e.message);
}
});

Make $.ajax call to url without knowing dataType

I'm trying to set up a generic call to webservices using jquery $.ajax. I'd like to be able to get raw data back and bind it to a grid.
I have calls working correctly when I know the dataType, but I want to try and make an ajax call without knowing the datatype, specifically to find what the dataType is.
For example, my ajax call knowing the datatype could be:
$.ajax({
type: 'GET',
crossDomain: true,
dataType: "jsonp",
url: 'http://itunes.apple.com/search?term=coldplay',
success: function (res, status, xhr) {
//DoStuff;
},
error: function (jqXHR, textStatus, errorThrown) {
//DoStuff
}
});
But any time I make a request without knowing the datatype I simply get a response status of "Error"?
What I would eventually like to be able to do with this is ping a url (webservice) that returns json, xml, or perhaps odata(unlikely). Since I won't know which, I want to be able to simply make a call to the url once to find out what kind of data I might get back, along with what content-type there is.
I've tried simply getting back the content type in the header in the error, but so far nothing I've tried has worked or returned anything at all.
$.ajax({
type: 'GET',
crossDomain: true,
url: 'http://itunes.apple.com/search?term=coldplay',
success: function (res, status, xhr) {
//DoStuff
},
error: function (jqXHR, textStatus, errorThrown) {
$("#results").html(textStatus + jqXHR.getResponseHeader('Content-Type'));
}
});
Can this even be done with Jquery?
Edit
I am aware that this can (and in most cases should) be done server side, and in all likelihood this is what will end up happening. But for the purposes of seeing how far I can go binding a grid to a datasource clientside without knowing my dataType the above question is born.
Thanks to all for the time.
Your approach is reasonable, but you are asking the user's browser to fetch information from a third party web server.
XMLHttpRequest cannot load http://itunes.apple.com/search?term=coldplay. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fiddle.jshell.net' is therefore not allowed access.
Unless the third party grants you permission, the Same Origin Policy will prevent your JavaScript from accessing any information about the response.
You should move your logic server side.

JQuery ajax call to cross-domain webservice

I would like consume cross-domain web-service from client with jquery
function TestService() {
$.ajax({
url: "http://service.asmx/GetGeoCompletionList",
data: { "prefixText":"eka", "count":"10", "contextKey":"Trace_0$Rus" },
dataType: "jsonp",
type: "GET",
contentType: "application/json; charset=utf-8",
success: function (data) {
alert(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.statusText);
}
});
}
At the error hander I have:
textStatus=parseerror
XMLHttpRequest has status 200 and readyState 4
errorThrown is jQuery16103495572647140...78197139 was not called
I've spent on it for a lot of hours and couldn't make it work. Can u help me?
UPDATED
Thanks, I change to GET, and fix my data string.
Service returns valid JSON object. I can see it at firebug on other site, which consume this service. But that site is getting common json(since it has one domain).
So, if the web-service returns valid JSON(not jsonp), I can't use the same method with jsonp? What can I do for consiming json web-service from other domain?
That string you are passing and claiming is JSON isn't JSON.
Only " characters may be used to quote strings.
Also, you can't make a cross domain JSON-P POST request.
You cannot do cross-domain POST requests using JSONP. JSONP works by adding script tags to the page. script tags always fetch their source using GET HTTP requests. You won't get any data posted.
Summary of problems:
Make sure you're using valid JSON
as #Quentin mentioned.
Make sure you're using GET requests, as
#lonesomeday mentioned
Make sure the response from the server is
JSONP, as seen here

jQuery + JSONP + Yahoo Query Language

I want to get live currency rates from an external source, so I found this great webservice:
Currency Convertor
This service is working like a charm, the only downside is that it does not provide JSONP results, only XML. Therefore we have a cross browser problem while trying to consume this webservice using jQuery $.ajax().
So I found Yahoo Query Language which returns results as JSONP and also mangae to consume other webservices and return me the results. This is also working, here is an example URL:
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fwww.webservicex.net%2FCurrencyConvertor.asmx%2FConversionRate%3FFromCurrency%3DNOK%26ToCurrency%3DEUR'&format=json&diagnostics=true&callback=cbfunc
This URL return JSONP result and is working like a charm, but the problem appears when I use this in my code:
$.ajax({
type: "GET",
url: urlToWebservice,
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
success: function(data) {
$("#status").html("OK: " + data.text);
},
error: function(xhr, textStatus, errorThrown) {
$("#status").html("Unavailable: " + textStatus);
}
});
When I try to run this code nothing happens, and I can see this error message in my Firebug javascript debugger:
cbfunc is not defined
cbfunc is the name of the container which surrounds the JSON response, but why does it say not defined?
EDIT:
This is my new code, but I still get the cbfunc is not defined
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fwww.webservicex.net%2FCurrencyConvertor.asmx%2FConversionRate%3FFromCurrency%3DNOK%26ToCurrency%3DEUR'&format=json&callback=cbfunc",
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'cbfunc'
});
function cbfunc(data) {
alert("OK");
}
And the "OK" message is never fired...
If available, use the jsonpCallback parameter in the call to $.ajax like:
jsonpCallback: "cbfunc",
Its description, from the jQuery API docs reads:
Specify the callback function name for a jsonp request. This value will be used instead of the random name automatically generated by jQuery.
The docs later go on to say:
It is preferable to let jQuery generate a unique name as it'll make it easier to manage the requests and provide callbacks and error handling. You may want to specify the callback when you want to enable better browser caching of GET requests.
However it is not advised to make use of this "preferable" behaviour when making use of YQL. Precisely why that approach is not ideal might make this answer far too verbose, so here is a link (from the YQL blog) detailing the problems with jQuery's preferred approach, making use of jsonpCallback and so on: Avoiding rate limits and getting banned in YQL and Pipes: Caching is your friend
You should let jQuery handle the callback by changing urlToWebservice to end in callback=?
The reason it's not working is because by specifying callback=cbfunc in the querystring generates a URL of the type:
http://query.yahooapis.com/...&callback=cbfunc&callback=jsonp1277417828303
Stripped out all uninteresting parts, but the URL contains two callback parameters. One of them is managed by jQuery, and the other one not. YQL only looks at the first callback parameter and returns a response wrapped around that.
cbfunc({"query":{...}});
However, there is no function named cbfunc in your script, so that's why you are getting the undefined error. jQuery created an implicit function named jsonp1277417828303 in the above example, and the response from YQL should instead have been:
jsonp1277417828303({"query":{...}});
for jQuery to act upon it, and return the response to your success callback which it never got to do.
So, as #SLaks suggested, remove the &callback=cbfuncfrom your URL, or replace it with &callback=? to let jQuery handle things.
See a working example.
You definitely should give jQuery-JSONP a try: http://code.google.com/p/jquery-jsonp/
Simplifies everything :)

Categories