I am using $.ajax inside the for loop in jquery.
for(var i=0; i < 2; 1++)
{
$.ajax({
url :"/models/getdata"+i
dataType:"json"
success:function(data)
{
}
});
}
before going success function for i=0; i=1 comes and performing the ajax request for this value. i want next iteration need to wait until current one gets completed.
that means one ajax request successfully completed and then it will increment the i value then start the next iteration.
consider another scenario also
function A()
{
$.ajax code
}
/////another operation
same here function A() need to wait until its ajax post get completed. but in my case it goes to next code start executing how can i stop further execution before current function gets completed. like sleep concept in C#
how can i do this ?
Thanks,
Siva
A simple generic solution :
var i=0;
(function doOne(){
$.ajax({
url :"/models/getdata"+i
dataType:"json"
success:function(data){
if (++i<2) doOne();
}
});
})();
For your second case, you may use the deferred returned by $.ajax :
function A() {
return $.ajax(...)
}
A().done(function(){
// some code executed after the ajax call finished
});
set async: false in the ajax call
This method could be the best way to handle this problem.
$.when(*AJAX CALL*)
.then(function() { // Function to run after ajax is completed
});
By default, all requests are sent asynchronously when we use $.ajax. By asynchronously, I meant, web applications can send data to, and retrieve data from, a server (in the background) without interfering with the display and behavior of the existing page. But you want execution to be stopped until your request is complete so set async to 'false'.
Use this -
$.ajax({
url :"/models/getdata"+i
dataType:"json",
async: false,
success:function(data)
{
}
});
Related
I am using jquery ajax api to call a web method, and on success i am implementing a functionality like showHideDomElement.
function showHideDomElement(data)
{
if(data == 1 )
$('#selector').show();
else
$('#selector').hide();
}
and this is how i call it
function Validatebatch() {
$.ajax({
type: "POST",
url: getControllerURL("/Invoice") + "/ValidateBatch",
data: {
"Id": $('#someselector').val()
},
async: true, // i tried with 'false' but it affect performance
dataType: "json",
success: function(data) {
showHideDomElement(data);
}
});
}
The ajax request to Validatebatch function raised multiple times, so there are multiple active http request pointing the url completing at different time.
Due to Asynchronous behavior, the success callback can execute at different orders.
The order of finishing up is creating the problem. Please suggest a way that can bound the ajax request to behave/complete in the order it is executed (Please suggest other than jquery async property)
Thanks
First of, you have to rewrite your Validatebatch function so it return the Promise generated by the $.ajax call, e.g.:
function Validatebatch() {
return $.ajax({
then you must store the promise of each Validatebatch call and use it to trigger the next Validatebatch only after the previous has completed, you should have something like:
promise = Validatebatch(); // call Validatebatch the first time and store the returned Promise object
promise = promise.then(Validatebatch); // another call to Validatebatch, only triggered after the previous has ended
promise = promise.then(Validatebatch); // again, this third Validatebatch call will only happen after the second one has ended.
This question already has answers here:
Easy to understand definition of "asynchronous event"? [closed]
(11 answers)
Closed 7 years ago.
I have the following Javascript and it's returning results out of the order I would expect them.
function getCurrentItems(id){
alert("2");
$.ajax({
url: "somePHPurlthatspitsoutajsonencodedArray.php",
type: "POST",
dataType: "json'",
data: {id:id},
success: function(data){
alert("3");
}
});
alert("4");
}
$(document).on('click', '.eventClass', function(e){
alert("1");
var id = "someID";
var results = getCurrentItems(id);
alert("5");
});
I would think I'd get alerts in the order of 1, 2, 3, 4, 5.
Instead I get them in the order of 1, 2, 4, 5, 3.
I just can't figure out why that success alert (5) fires last?
AJAX is short for asynchronous JavaScript and XML. Asynchronous is the keyword here. I'll use an allegory to explain async.
Lets say you're washing dishes manually. You can't do anything else while doing that, so it is synchronous.
Lets say you put your dishes in a dishwasher. You can do other things, you've delegated the task to the dishwasher, so this is asynchronous. Asynchronous is generally better, because you can do multiple things at one time. Javascript only asyncs when requesting info from the server, as Javascript is single threaded (it only runs on 1 CPU core and can only do one thing at a time on it's own).
A callback is a function that is called when the async task completes. The dishwasher finishes, so now you have to empty it as soon as you complete what you're doing when it finshed.
So in your code, you start the dishwasher, say you're going to alert("3") when the dishwasher finishes running, and then you go alert 4 and 5. Then when the dishwasher finishes/your server returns data, you alert 3 like you said you would.
That make sense?
The reason that you give a success callback function in an ajax request is that the request might take some time to return, but your code can continue running. In this case the ajax request is sent, and the success function is remembered for later, then your code continues (alerting 4 and 5). When the browser receives the response to the ajax request it calls the success function (alerting 3).
The way that Javascript works, only one thread is run per browser tab, so event handlers are not called until any previously running code is completed. Therefore, even if your getCurrentItems function were to take several seconds to complete, by which time the server response had returned, the success function would still not be called until after your function had completed.
Edit: Because an ajax call can take some time, it is not generally desirable to be able to call a function like getCurrentItems which includes an ajax request, and wait for the response. If you do this, then you are likely to leave your browser window unresponsive, and you will have to deal with potential errors from the ajax call. Instead, you should put any code that you wish to run which relies on the ajax result in the success function, or in another function which you call from there. As languages go, Javascript is very good for doing this kind of thing. You could even take a callback function as an argument to getCurrentItems, and run it from the success function.
As others have mentioned, you're getting the results in the order you see because the ajax request doesn't return with it's data and call your success callback until the response is received, but code continues to execute immediately after the $.ajax call.
To get the workflow you're probably expecting, you could use promises, or simply pass in a callback:
function getCurrentItems(id, onSuccess){
alert("2");
$.ajax({
url: "somePHPurlthatspitsoutajsonencodedArray.php",
type: "POST",
dataType: "json'",
data: {id:id},
success: function(data){
alert("3");
onSuccess(data);
}
});
alert("4");
}
$(document).on('click', '.eventClass', function(e){
alert("1");
var id = "someID";
var results = getCurrentItems(id, function(data){
console.log('data',data);
alert("5");
});
});
Is there a way to pause the rest of a function when you are waiting for a value to be returned from an asynchronous call with jQuery?
To achieve this "paused" behavior, you want to put the behavior inside the promise object. https://api.jquery.com/jQuery.ajax/
$.ajax({
url: "test.html",
data: myData
}).success(function() {
//put your code here this will only fire after it returns successfully
}).error(function() {
//This will fire if there is an error
});
What you are talking about would be a synchronous call, which is not recommended as it will freeze the UI.
Instead, use the callback provided in the jQuery call to perform the rest of your code:
function DoSomeCall()
{
$.post( "ajax/test.html", function( data ) {
//Do your follow on code in here, in the callback.
});
//Don't do any code here that relies on the AJAX being finished first.
}
Why is x undefined at line 11 when it is defined in line 9?
<script>
var x;
$.ajax({
dataType: "json",
url: myurl,
success: function(data){
console.log(data);
x = data;
document.write(x);
}
});
document.write(x);
</script>
Because you have asynchronous behavior here.
The flow of your program is actually like this:
1- You declare x
2- You make an ajax request
3- You write x into the document (at this point, x has no value)
4- The ajax request gets a response and you set x's value to that response and write it on the document.
Your problem is not a matter of scope, it's a matter of timing.
That is because line 11 gets executed before the Ajax(Asynchronous) callback function success executes and set the value at line 8.
You may do this instead.
function MakeAjaxCall(callback)
{
$.ajax({
dataType: "json",
url: myurl,
success: function(data){
console.log(data);
callback(data);
}
});
}
function wantToCallAjaxAndUseResult()
{
MakeAjaxCall(function(x){console.log(x)});
}
This has more to do with AJAX being asynchronous, rather than variable scope. Control immediately proceeds to line 11 where x is not defined. However, line 8 will be executed at some indeterminate point in the future (i.e., after the request is finished and the success callback is called and executed), after line 11 has executed.
Ajax runs asynchronously. JavaScript makes a request and continues executing other code while waiting for the request to complete. This means that you can't depend on when the request will complete or even if it will complete. Thus all work that depends on the result of an ajax call must be done in the ajax callback. You simply can't rely on anything that happens inside of the ajax callback having an effect on anything outside of the callback at any time.
I have the following code which is included in a keypress function:
$.getJSON('dimensions.json', function(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
});
I'm trying to first get the JSON string, save it in a variable and then run the each(). I want to basically separate the each() to be unlinked to the getJSON() function because I don't want it to fetch the json file for every keypress.
I've tried this, but it didn't work:
var JSONstr = $.getJSON('dimensions.json');
$.each(JSONstr, function(index) {
$('#div1').append(index);
});
In your first example, you do $.each in the callback. The callback is executed by some other callback after there result is received, while $.getJSON returns immediately without waiting for the result (since there is no blocking in JavaScript by design).
Therefore the code in your second example can never work: the $.each begins before any result is received from the web server, probably even before the request is sent. Whatever the return value of $.getJSON is, it can't, by the design of JavaScript, be the result of AJAX request.
UPD: Saw your comment, now I understand what you wanted to do. Here's a simple example of how to do this:
function ActualHandler(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
function KeypressHandler() {
if (window.my_data) { // If we have the data saved, work with it
ActualHandler(window.my_data);
}
else { // Otherwise, send the request, wait for the answer, then do something
$.getJSON('dimensions.json', function(data) {
window.my_data = data; // Save the data
ActualHandler(data); // And *then* work on it
});
}
}
Here, the ActualHandler is not launched before the data is received, and once that happens, all subsequent clicks will be handled immediately.
The downside in this particular case is that if user clicks again while the first request is running, one more will be sent. But to fix that you would need to maintain some queue, which is kind of out of scope here.
You fell into the asynchronous trap. Your $.each() function doesn't wait for your $.getJSON() call to get the data. You can get around this by using the good 'ol $.ajax() function. Like this:
function processJSON(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
$.ajax({
url: 'dimensions.json',
dataType: 'json',
async: false,
success: processJSON(data)
});