This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it posible to use ajax respone outside of it?
I've created the following JavaScript routine that goes to a WCF oData service and gets some data. In the success element I get the results into the results variable and alert them - I see that there are objects returned. When I run the second alert, outside of the ajax call and before returning the results, the results variable is "undefined".
Can anyone please tell me where I'm going wrong?
function retrieveJsonpODataSet(baseUrl, query)
{
var oDataUrl = baseUrl + "?$format=json&$callback=?";
var results;
$.ajax(
{
url: oDataUrl,
contentType: 'application/json; charset=utf-8',
type: 'GET',
dataType: 'jsonp',
async: false,
success:
function (data, textStatus, xhr)
{
results = data.d;
alert(results); // This shows the results
},
error:
function (xhr, textStatus, errorThrown)
{
alert("Query failed.\n\n" + oDataUrl + "\n\n" + errorThrown);
results = null;
}
});
alert(results); // This shows "undefined"
return results;
}
Please ignore the query parameter - I've not finished the routine yet.
EDIT
Initially I had no async:false in the ajax call. I've added that now but it doesn't fix the problem.
The ajax call is an asynchronous operation. It fires and your code does not stop at it. So results is returned which at that point is undefined. What you need to do is to pass callback to the function.
function retrieveJsonpODataSet(baseUrl, query, callback) {
/* some code */
$.ajax({
/* some settings */
success: function(res) {
/* some code */
callback(results);
}
});
}
Now you use it like this
retrieveJsonpODataSet(baseUrl, query, function(res) {
/* Hurray, I have result now in res variable! */
});
DO NOT USE async: false OPTION! It blocks ALL scripts untill the call finishes... and what if it does not finish at all?? You will be blocked forever.
EDIT
I've missed that the request is JSONP. In that case async: false won't even work (it does not work for cross-domain requests and JSONP). So you have to use callbacks anyway.
A fellow Richard!
This isn't a scope issue, but more of an execution one. Both the success and error options are event handlers, and run asynchronously (hence it being called AJAX). This essentially means that the alert(results) and return results can, and likely will, get executed before the success or error events are triggered.
Your ajax is async, so the alert executes before the ajax completes. You need to set the ajax call async property to false in order for script to halt the execution until ajax request is made & processed.
However, jQuery docs says:
async
Default: true
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false is deprecated.
AJAX request are sent, without the script waiting for a response, that's what Dave Newton means by A-synchronus, put the alert inside the success callback function, and you'll see what the actual response is.
alternatively, you can specify the async property, and set it to false, to force your script to wait for the response, before continuing.
Related
I am pretty much new to ajax and working on jquery ajax request. Ajax callback is not calling success method. Interaction is between cross-site domains.
My AJAX request looks like
$.ajax({
timeout: 20000,
url: 'test.com',
crossDomain: true,
dataType: 'jsonp',
success: function (data) {
console.log('callback success');
this._cache = data;
localStorage.token = data.access_token;
} });
There are no errors in this call.
This ajax request is not calling success function.Request is returning json data. it's just success method is not getting called.
This ajax request is not calling success function.
Get request is getting fired successfully. I can even trace the response in fiddler with 200 http response.For some reason success method is not getting called.
it's returning json object, which I've traced in fiddler
You're telling jQuery to expect a JSONP response, so it is trying to execute the JSON document as if it were a JavaScript script (because that is what JSONP is). This fails because it is not JSONP.
Either return JSONP instead of JSON or (assuming the server returns the correct Content-Type) remove dataType: 'jsonp',.
ok... I came here with the same problem... and when I read that specifying datatype:jsonp never calls success as a callback per #mondjunge from a comment above, it started me thinking about some behavior I saw earlier from my code and that maybe datatype:json might have the same behavior for what ever reason here too.
So after reading this page I took out my datatype declaration from my ajax request and my servlet returned the proper data payload, returned a 200, and jquery called the success function finally and modified my DOM.
All those steps happened except the last one until I removed my datatype from my ajax call. NOT what I was expecting!
Hopefully someone else can shed some light on why this happens... for now at least the few that don't lose their minds to this issue that find this post can do this in the mean time.
Check if your ajax is executed
Check it's status. If response code is != 200, than you should add error method also, for error handling.
Try this:
$.ajax({
timeout: 20000,
url: 'test.com',
method: 'GET',
crossDomain: true,
dataType: 'jsonp',
success: function (data) {
console.log('callback success');
this._cache = data;
localStorage.token = data.access_token;
},
error: function(xhr, error){
console.debug(xhr); console.debug(error);
},
});
I'm using JQuery to make JSONP requests and the documentation is quite confusing.
I have several questions:
A JSONP call is always async, is that correct? So the async:false would be simply ignored?
If the jsonpCallback parameter is specified, this function will be executed when the data are retrieved. But right after, also the success callback will be executed. Jquery advices NOT to specify the jsonpCallback function(only for caching?). What is the role of this function in relation with the success function?
If the jsonpCallback is not specified a random callback function will be created and attached to the window object. Something like jQuery1360574548776335413_1776656584447, what is its role? How does it work? Does it have any relation with the success function?
Is the error callback never called?
Here's my code:
(function($) {
var url = "https://www.googleapis.com/books/v1/volumes/zyTCAlFPjgYC";
$.ajax({
type: 'GET',
url: url,
// JSONP always async?
async: false,
jsonp: "callback",
jsonpCallback: 'jsonCallback',
contentType: "application/json",
dataType: 'jsonp',
success: function(json) {
console.dir(json);
},
// Error never called?
error: function(e) {
console.log(e.message);
}
});
})(jQuery);
function jsonCallback(json) {
$(".test").html(json.volumeInfo.title);
}
A JSONP call is always async, is that correct? So the async:false would be simply ignored?
That is correct
If the jsonpCallback parameter is specified, this function will be executed when the data are retrieved. But right after, also the success callback will be executed. Jquery advices NOT to specify the jsonpCallback function(only for caching?). What is the role of this function in relation with the success function?
The success function is your callback. Jquery generates a random function name usually. If, however, you're making several of the same requests and would instead like to allow the browser to cache calls, you can specify the function so that a randomly generated one is not created. Inspect the network requests and you'll see (as long as your server is set up to support it) that if you specify the name, you should get 304 - Not Modified (edit: on subsequent requests after the first), while other calls always return 200 OK
If the jsonpCallback is not specified a random callback function will be created and attached to the window object. Something like jQuery1360574548776335413_1776656584447, what is its role? How does it work? Does it have any relation with the success function?
Is the error callback never called?
That callback function should contain the code you put in success. The error event is fired if there is an error with the actual request, such as an invalid domain name, 401 server response, and etc.
I have the following JS/JQuery snippet:
function add_item() {
var item = $("input:text[name='new_item']").val();
$.post("{{ url_for('add_item') }}",
{'item' : item},
function(data) {
alert(':}');
});
}
It performs a simple AJAX request to a Flask webserver and displays an alert box on success (the data always returns a JSON snippet). The AJAX request adds a field to a SQLite database and returns. On my dev box, this request completes very quickly using asynchronous requests. However, on another server this request takes a few seconds (less than the default timeout, though) using asynchronous requests.
Problem: When the request takes a long time to complete using asynchronous requests, the callback is never called. When I change the AJAX settings to be synchronous, the callback is always called.
Thank!
I would try the $.ajax() function over the post one. Seems to have been more maintained - 1.6.2 also seems to have some issues, so try 1.6.1 if you need to: http://api.jquery.com/jQuery.ajax/
Use the error method to find out what error you're getting.
function add_item() {
var item = $("input:text[name='new_item']").val();
$.post("{{ url_for('add_item') }}",
{'item' : item},
function(data) {
alert(':}');
}).error(function(jqXHR, textStatus, errorThrown) { alert("error"); });
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
the question is fairly simple and technical:
var it_works = false;
$.post("some_file.php", '', function(data) {
it_works = true;
});
alert(it_works); # false (yes, that 'alert' has to be here and not inside $.post itself)
What I want to achieve is:
alert(it_works); # true
Is there a way to do that? If not can $.post() return a value to be applied to it_works?
What you expect is the synchronous (blocking) type request.
var it_works = false;
jQuery.ajax({
type: "POST",
url: 'some_file.php',
success: function (data) {
it_works = true;
},
async: false // <- this turns it into synchronous
});
// Execution is BLOCKED until request finishes.
// it_works is available
alert(it_works);
Requests are asynchronous (non-blocking) by default which means that the browser won't wait for them to be completed in order to continue its work. That's why your alert got wrong result.
Now, with jQuery.ajax you can optionally set the request to be synchronous, which means that the script will only continue to run after the request is finished.
The RECOMMENDED way, however, is to refactor your code so that the data would be passed to a callback function as soon as the request is finished. This is preferred because blocking execution means blocking the UI which is unacceptable. Do it this way:
$.post("some_file.php", '', function(data) {
iDependOnMyParameter(data);
});
function iDependOnMyParameter(param) {
// You should do your work here that depends on the result of the request!
alert(param)
}
// All code here should be INDEPENDENT of the result of your AJAX request
// ...
Asynchronous programming is slightly more complicated because the consequence
of making a request is encapsulated in a function instead of following the request statement. But the realtime behavior that the user experiences can be significantly
better because they will not see a sluggish server or sluggish network cause the
browser to act as though it had crashed. Synchronous programming is disrespectful
and should not be employed in applications which are used by people.
Douglas Crockford (YUI Blog)
AJAX stands for Asynchronous JavaScript and XML. Thus, the post to the server happens out-of-sync with the rest of the function. Try some code like this instead (it just breaks the shorthand $.post out into the longer $.ajax call and adds the async option).
var it_works = false;
$.ajax({
type: 'POST',
async: false,
url: "some_file.php",
data: "",
success: function() {it_works = true;}
});
alert(it_works);
Hope this helps!
It seems that your problem is simply a concurrency issue. The post function takes a callback argument to tell you when the post has been finished. You cannot make the alert in global scope like this and expect that the post has already been finished. You have to move it to the callback function.
The reason your code fails is because post() will start an asynchronous request to the server. What that means for you is that post() returns immediately, not after the request completes, like you are expecting.
What you need, then, is for the request to be synchronous and block the current thread until the request completes. Thus,
var it_works = false;
$.ajax({
url: 'some_file.php',
async: false, # makes request synchronous
success: function() {
it_works = true;
}
});
alert(it_works);
I am doing AJAX with JQuery but every time the "onSuccess" event must be executed after another AJAX request disconnected.
Here is the code:
d.ajax({
url: f.options.url.offline,
dataType: "jsonp",
jsonp: "callback",
cache: false,
data: {
status: "offline",
ticket: f.connection.options.ticket
},
success: function(g) {
f._offlineSuccess()
},
error: function() {
f._offlineError()
}
})
All my AJAX requests are JSONP, and when the above code is triggered, there is another AJAX connection (long polling request, last about 10 senconds) already established in the mean time. So the "f._offlineSuccess" function is always executed after another AJAX connection disconnected.
I can not see any relationship between the two AJAX requests, and I don't know why the "onSuccess" function must be executed after another AJAX connection stopped.
Any help is appreciated~
================================
updated:
I just found out if I have two JSONP connection at the same time, the "onSuccess/onFailure" function will be blocked. I don't know if some one encountered the same problem before?
Ajax requests are asynchronous. so a new request is not going for the previous one to finish. If you want that behaviour use async parameter to false, or use the complete() function to call for another request. This will fire only when the first request is finished.
UPDATE
For JsonP use jQuery.getJSON() and do the second request on callback if the call was succesfull.
function (data, textStatus) {
// data will be a jsonObj
// textStatus will be one of the following values:
// "timeout","error","notmodified","success","parsererror"
this; // the options for this ajax request
}
If you use firebug - net tab, you will be able to see the full url of the two jsonp requests. You should be able to see the callback function names on the end of the url. Are these different or the same? I can only assume they are the same.