When I look at the query string from a jsonp request (client code below), there are 2 objects, a "callback" string that you need to use in the response (so the client codes directs to the success handler) and one with a key of _... what is this underscore for? I can't find any reference to this in any documentation, it appears to be a number of some kind.
I though that it might be used to direct to the error handler (either on its on, in combination with the callback, or replacing the number after the underscore in the callback string), but it doesn't appear to be.
url = 'http://localhost:11767/Handlers/MyHandler.ashx';
...
$.ajax({
url: url,
dataType: "jsonp",
error: function (jqXHR, textStatus, errorThrown) {
//...
},
success : function(d) {
//...
}
});
or
$.getJSON(url + "?callback=?", function(d) {
}).success(function(d) {
//...
}).error(function(jqXHR, textStatus, errorThrown) {
//...
}).complete(function(d) {
//...
});
Side note in case this helps anyone reading this: as this is a jsonp request, error will only be hit if the exception occurs client side, e.g. there is a timeout or a problem with the formatting of response (i.e. not using the callback), to overcome this, I always log and swallow the exceptions in the handlers, but give a standard response object (which all response are made up of) that has a state property of exception and a message property.
The number you are referring is the date time stamp of the request. Grab the number and use a your browser's JavaScript console and type: alert(new Date(/*insert number here*/))
You'll get an alert with a date/time.
EDIT:
Here's a snippet from jQuery.ajax doc regarding an ajax request:
cache
Default: true, false for dataType 'script' and 'jsonp'
If set to false, it will force requested pages not to be cached by the browser.
Setting cache to false also appends a query string parameter, "_=[TIMESTAMP]",
to the URL.
Related
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.
$.ajax({
url: "/Configuration/AddServersAdvancedSelect",
type: "POST",
data: { selectedOUs: that.getByDataSelected() },
async: false,
dataType: "html",
success: result => {
cont.setTabContentFromHtmlString(result, 1);
cont.tabClicked($("td[data-value='1']").get(0));
},
error: (xhr, ajaxOptions, thrownError) => {
//
}
});
EDIT: I came back to work today and it magically started working. I guess that's something
This is my ajax request towards the server. For some reason the data doesn't get selected. The getByDataSelected function works just like it should and reuturns good values. The Controller method has the name selectedOUs and everything matches. Does anybody have any idea as to why this ajax POST doesn't send data?
jQuery defines the data parameter as
Type: PlainObject or String or Array
Data to be sent to the
server. It is converted to a query string, if not already a string.
It's appended to the url for GET-requests. See processData option to
prevent this automatic processing.
Object must be Key/Value pairs.
If value is an Array, jQuery serializes multiple values with same key
based on the value of the traditional setting (described below).
I'd be willing to bet that your return value of that.getByDataSelected() is not consistent with the expected parameter if it isn't getting sent.
In this case, your error function should be receiving an Internal Server Error [500]
I want to execute the following AJAX call (cross domain):
$.ajax({
type: 'GET',
url: url + "?callback=?",
contentType: 'application/json',
async: false,
jsonp: "callback",
dataType: 'jsonp',
success: function (json) {
alert("ok" + JSON.stringify(json));
},
error: function (json) {
alert("err" + JSON.stringify(json));
}
});
And I am getting this alert message:
err{"readyState":4,"status":200,"statusText":"success"}
Which means the code ends in the error method.
If I check the request in Firefox or Chrome, the JSON part of the response is available and clearly formatted. Is it possible to get the JSON response in the error method? Or do you have any idea why the success method isn't hit?
It's not my server unfortunately, so I can't implement any changes on the server side. I used http://jsonlint.com/ to validate the JSON output and it is Valid. Entering the same URL in the browser returns the JSON content correctly.
Thanks much in advance,
I tried a few different approaches, but still failing on the error method,
[EDIT]
SO, I am playing with different approaches, always getting the same error. If I change the error part of my call to this:
error: function (jqXHR, textStatus, ex) {
console.log(arguments);
alert(textStatus + "," + ex + "," + jqXHR.responseText);
}
Then I am getting the following error:
http://i.stack.imgur.com/ck6Sd.png
Copy paste of error for search engines:
0: Object
1: "parsererror"
2: Error
message: "jQuery11020553141210693866_1392367304225 was not called"
stack: (...)
get stack: function () { [native code] }
set stack: function () { [native code] }
proto: d
callee: function (jqXHR, textStatus, ex) {
length: 3
proto: Object
The same things apply as above, the response is readable in the browser without issues.
EDIT2
I ended up doing the JSON call the old way, embedding it into the page:
script = document.createElement("script");
script.type = "text/javascript";
script.id = "resultJSON";
script.src = url;
$(".resultsOutput").append(script);
But I have troubles retrieving the data, the script tag seems to be empty. I am getting an error on the JSON:
Uncaught SyntaxError: Unexpected token :
Anyone able to help? I am starting to get desperate on this one. It seems that the issue is that the JASON is returned without a method wrapper.
[LAST EDIT]
So, turns out the server doesn't support CORS and the returned JSON isn't wrapped in a JS function, so this approach won't work. I'll have to use some other approach to retrieve the data.. thanks everyone for reading
Andy
Is there any particular reason to:
Override random callback name jquery gives?
Set datatype to application/json?
This second one may be causing the error. If I'm correct, the server would return application/javascript mime-type, since it should return the JSON you are looking for wrapped into a callback function that shall be called once the request hast completed. Something like this:
function callback() {
return {"a","b"} //the JSON you are looking for
}
This all is handled internally by creating a tag "script" to avoid cross-domain browser restrictions, so you cannot handle JSON directly, it needs to be wrapped into Javascript code. Thus, contentType may be wrong.
Try removing the contenType property on the ajax options and see how jquery behaves (it should interpret content-type from response headers from the server).
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.
I am using jsonp and ajax to query a web-service written in java on another server. I am using the following jquery command:
$.ajax({
type: "GET",
url: wsUrl,
data: {},
dataType: "jsonp",
complete: sites_return,
crossDomain: true,
jsonpCallback: "sites_return"
});
function jsonp_callback(data) {
console.log(data);
}
function sites_return(data) {
console.log(data);
}
So my problem is that after the query finishes a function called jsonp_callback is called. Where I can clearly see the json formatted string:
{"listEntries":["ELEM1", "ELEM2", "ELEM3", etc...]}
But after the function sites_return is called when the complete event fires, I get the the following:
Object { readyState=4, status=200, statusText="parsererror"}
Also for reference the jsonp_callback function is called before the sites_return function. Also if i take the jsonp_callback function out of the code, I get a complaint it firebug that the function is not implemented.
My question three fold:
1) What am i doing wrong on the jquery side?
2) Why does the json get parsed correctly in jsonp_callback but not sites_return?
3) What can i do to fix these issues?
EDIT
Some new development. Per the comments here is some additional information.
The following is what comes out of the http response
jsonp_callback({"listEntries":["ELEM1", "ELEM2", "ELEM3"]})
I assume this is the reason jsonp_callback is being called. I guess my question now becomes, is there any way to control this (assuming i don't have access to the back end web-service).
Hope this helps~
var url = "http://maps.google.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false";
var address = "1600+Amphitheatre+Parkway";
var apiKey = "+Mountain+View,+CA";
$.getJSON("http://maps.google.com/maps/geo?q="+ address+"&key="+apiKey+"&sensor=false&output=json&callback=?",
function(data, textStatus){
console.log(data);
});
I believe that the first argument to the sites_return function would be the jqXHR Object. Instead of complete try using success.
But still this may not work as it seems that there is a parsing error (mentioned in the return value of sites_return function called from oncomplete). Therefore, you would first need to check your json string.
To Validate JSON, you can use http://jsonlint.com/
I think that the problem is that your server is not behaving the way jQuery expects it to. The JSONP "protocol" is not very stable, but generally what's supposed to happen is that the site should look for the "callback" parameter and use that as the function name when it builds the JSONP response. It looks as if your server always uses the function name "jsonp_callback".
It might work to tell jQuery that your callback is "jsonp_callback" directly:
$.ajax({
type: "GET",
url: wsUrl,
data: {},
dataType: "jsonp",
complete: sites_return,
crossDomain: true,
jsonpCallback: "jsonp_callback"
});
Not 100% sure however.
If you don't have the ability to change the JSONP function wrapper that the remote server returns, jQuery's $.ajax() may be overkill here. Ultimately, all you're doing is injecting a script reference to wsUrl, which makes a call to jsonp_callback with a JavaScript object literal as its input parameter.
You could just as easily do something like this and avoid the confusion around the callback naming/syntax:
$.getScript(wsUrl);
function jsonp_callback(response) {
// Access the array here via response.listEntries
}