jQuery Ajax run, Why? [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have script following:
var price_option_oc = 0;
// Example
jQuery.ajax({
type: "POST",
processData: false,
dataType: "text",
url: mainURL + url_ajax_get_prices_oc,
data: JSON.stringify(datas),
contentType: "application/json; charset=utf-8",
}).done(function(data) {
console.log('{1}=' + data);
price_option_oc = data;
});
console.log('{2}' + price_option_oc);
Why result is, I dont know why, please explain for me
{2}0
{2}0
{1}=9
{1}=9
Why not is:
{1}=9
{1}=9
{2}0
{2}0
Thanks.

Ajax requests run asynchronously to the rest of your code. That is, they run in parallel.
So it's very likely that
console.log('{2}'+price_option_oc);
is running before the ajax call completes and runs console.log('{1}='+data);
I say "very likely" because, since the ajax call relies on external factors like network speed and the response speed of the remote server, you can't guarantee how fast it will run, and therefore you can't guarantee the order things will run in.
If you need to run code which depends on the response from an ajax call, then you must put that code into your .done function (or into a function which is called from there).
P.S. I would not use async:false to solve this type of issue - this will cause the browser to stop responding to any user input until the ajax call completes (or fails). If the call takes longer than normal, it will look to the user like their browser has crashed. This is not user-friendly. Most coders don't use this feature for that reason.

Related

How to specify an asynchronous request in API JavaScript [duplicate]

This question already has answers here:
How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
(14 answers)
Closed 6 years ago.
I want to send to server (php) a request AJAX from an api javascript:
JS File :
var commit = new Object();
commit.id= this.id;
commit.action = this.doCommit;
commit.vrp= this.vrp;
$.post(this.ajaxURL, commit);
with this code i can send a request but in mode asynchroun. I searched on internet and I found a solution :
$.ajax({
type: 'POST',
url: this.ajaxURL,
data: commit,
async:false
});
I don't know if it is the best solution, or I can precise async:false in a $.post request, if yes , how ?.
So you do or you do not want to send the request asynchronously? The question seems to be confusing for me. But by default, $.ajax({... is always async, and $.post is just a shorthand way to write a simple post ajax request, which is also async. If you use the async:false, you are telling the javascript to not continue to execute the next line of code until the request finishes.

jQuery .ajax or .post taking too long message [duplicate]

This question already has an answer here:
Run function if jQuery.ajax waiting for respond long enough
(1 answer)
Closed 8 years ago.
I know about the timeout setting for the ajax call. But what i'm wondering is, is there a way to display a message to the user if an ajax call is still processing but taking longer than x seconds.
E.g.
During an ajax call, if it takes longer than 10 secs tell the user, "call taking longer than expected"
I'd say your best bet is to use window.setTimeout for however long you want to wait for before showing your notification, and then add a window.clearTimeout line to your success callback in your $.ajax() call:
var loadingTimeout = window.setTimeout(function() {
// show your warning here
alert('Still loading :P');
}, 10000); // 10000ms = 10sec
$.ajax({
url: 'http://your/url/here',
dataType: 'json',
type: 'GET',
success: function(r) {
window.clearTimeout(loadingTimeout);
// your results logic here
}
})
Sure, just setTimeout() yourself another function that checks some global variable that gets set by the ajax completion callback. In that function, if the ajax call is still outstanding, show a message.

How to make a function return data retrieved via AJAX [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
In my javascript file, I use the function above to get asynchronously a value calculated by the server:
function function2(userid)
{
$.ajax({
type: "POST",
url: "http://localhost/bghitn/web/app_dev.php/get_number_of_articles",
data:{id:userid},
cache: false,
success: function(data){
return data;
}
});
}
In fact, I call the function2 inside a set of functions:
function1();
var userid=.....
var x= function2(userid);
function3(x);
The problem:
as you see, function3 uses the data returned by function2. But it seems that function3 starts executing before the AJAX call is successfully finished. I tried to use the when function but in vain.
$.when(function2(userid)).done(function(){
function3();
});
How to make the next javascript code executes after the preceding AJAX request is successfully performed? Your advices are highly appreciates.
Option 1: You can always set your AJAX call to be synchronius, but be ready that the whole page stucks while waiting for response. just add parameter async: false to your set of parameters.
Option 2: Provide callbacks or put your future code inside success handler
Option 3: You can use defer/promise described here http://blog.mediumequalsmessage.com/promise-deferred-objects-in-javascript-pt1-theory-and-semantics

Queue multiple AJAX requests, waiting for response and not freezing browser? [duplicate]

This question already has answers here:
Sequencing ajax requests
(10 answers)
Closed 9 years ago.
I am working a script, I need to loop an array of AJAX requests:
$('#fetchPosts').click(function(){
for(var i=0; i < link_array.length; i++) {
settings = {
// some object not relevant
}
var status = main_ajaxCall(settings, i); // ajax call
}
});
function main_ajaxCall(settings, i) {
$.ajax({
type: "POST",
url: "../model/insert.php",
data:{obj_settings: settings},
dataType: "json",
cache: false,
success: function (data) {
// some handeling here
return 0;
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
return 1;
},
};
Why does the AJAX requests fire instantly? It does not seem to wait for a response from model/insert.php, is there any way to force it to wait for a response before firing the next AJAX request?
EDIT 1:
It seems I wasnt clear, sorry, I dont want it to wait, I want to queue up the calls.
I cant make the call in one request, this is impossible in my current situation.
Set async to false if you want to wait for a response (default: true)
$.ajax({
async: false,
...
http://api.jquery.com/jQuery.ajax/
If you do not want blocking, you can set a success handler function using .ajaxComplete(), and you have to keep track of active AJAX connections if you want to wait for all to complete - How to know when all ajax calls are complete
The best solution would be to minimize the number of AJAX requests to one. If you have to make a loop of AJAX requests, the logic could be simplified somewhere (put that in the server perhaps?)
EDIT 1: (In response to OP edit)
If you want to queue the AJAX requests, this question has been answered before here:
Sequencing ajax requests
Queue ajax requests using jQuery.queue()
You could also use these libraries (all you needed to do was Google):
https://code.google.com/p/jquery-ajaxq/
http://codecanyon.net/item/ajax-queue-jquery/full_screen_preview/4903957
http://schneimi.wordpress.com/2008/03/10/multiple-ajax-requests-problems-and-ajaxqueue-as-solution/
It fires instantly and doesn't wait around because that's what AJAX does best (The first A stands for asynchronous).
The request to a server could take a long time to respond, and in most cases, don't want user's browser's freezing up or stopping them from doing anything else. If you do, you could probably just use a normal request.
This is the reason you give it functions for success error, so it can call them when the server responds.
If you want nothing to be able to happen in the browser while you're calling insert.php, you could drop an overlay (eg. dark div) over everything with a loading image and remove it on success.
Maybe replace the $('#fetchPosts') element with "loading..." text and then reverse it when done. Hiding visibility of the fetchPosts element and adding a different "loading.." element is a nice way.
Your AJAX call will wait for a response from the server, but wil do so asynchronously. That is, your script will continue to execute rather than block the browser while the server responds. When the server responds (or when the request times out - usually several seconds) your success: or error: functions will then execute.
The effect of your code here is to create several concurrent requests based on the link_array length.
You could specify async:false in your AJAX call, but this would freeze the browser while all the AJAX calls are made.
You should rewrite your code to execute all the handling as part of your success: function. I'd recommend you rewrite your code to assemble all your request into one, and make one AJAX call rather than several, and have the server return all the responses as one block. I can't suggest exactly how you do that - it's implementation dependent.
EDITED:
In response to your clarification, if you want them to be called in order, you'll need the success function to call the next one. You'll then have a chain of success calls the next, whose success calls the next, whose success calls the next.. etc until the last one which does the final processing. One way would be to pass the call number to the success function.

JavaScript Synchronous Ajax Request Idiosyncrasies

I'd like to preface this with an apology if I'm doing things in a "weird" way, as I'm primarily a C developer and am solving this AJAX problem the way I would in C.
I have a script that will be connecting to a "push server" that waits until a message is available, then sends only that one message and breaks the connection. The client must then reestablish the connection to listen for future messages.
I tried to do this by implementing a synchronous AJAX call within an asynchronous callback, and it works except it appears the DOM (maybe? I'm showing my ignorance of JS here) will block until all calls are complete.
I do not know how to do it with purely asynchronous calls as I do not want to end up exhausting the stack by having a callback calling a callback each time.
This is the code:
$.ajax({
url: './recoverDevice',
data: JSON.stringify(requestData),
dataType: 'json',
type: 'POST',
success: function(j)
{
console.log(j);
if (j.success)
{
//Indefinitely listen for push messages from the server
var loopMore = true;
while(loopMore)
{
$.ajax({
async: false,
url: './getPendingMessage',
dataType: 'json',
type: 'POST',
success: function(j)
{
//alert(j.message);
$("#progressBox").append("<li>" + j.message + "</li>");
loopMore = !j.complete;
}
});
}
}
else
{
$("#errorBox").show();
$("#errorBox").text(j.errorMessage);
}
}
});
Now, logically, this code should work. Within an asynchronous function, I loop over a synchronous JS call, each time I get a message I will append it to the DOM, and only when the server tells me there will be no more messages do I exit the loop, ending the asynchronous thread and completing the task.
The problem is that the DOM access appears to be all coalesced once all messages have been received. i.e. the appends only happen once all messages have been received and the asynchronous thread has exited.
The commented out alert was a test - it works perfectly. I get a message box after each and every notification, and it pauses correctly until the next message (with the rest of the code as-is).
I'm guessing this is my browser (Chrome) doing some magic to protect against race conditions by not allowing DOM manipulation until the asynchronous thread has exited? Or am I way off the mark and barking up the wrong tree here?
Getting rid of the loop and setting async to true makes the first message be received properly (no problems there), but obviously no messages thereafter.
Obviously I could do something like this:
function GetMessage()
{
$.ajax({
async: true,
url: './getPendingMessage',
dataType: 'json',
type: 'POST',
success: function(j)
{
$("#progressBox").append("<li>" + j.message + "</li>");
if (!j.complete)
{
GetMessage();
}
}
});
}
But that would result in a stack overflow over time (no?).
An obvious solution would be to use asynchronous calls here too, but to signal a while loop to pause and continue with new calls via some sort of synchronization primitives, but appears that JS does not have signalling primitives?
Figured this one out - I don't know why I didn't see this before but my latter code fragment works perfectly. I didn't realize it at the time of posting, but it can't overflow the stack because each time it runs it launches an async call and exits - so the stack frame is never more than 2 or 3 deep. The asynchronous calls are managed externally and won't be on the stack, so each time it starts over.
I'd still appreciate any input on why the first method (synchronous code in asynchronous call) didn't/wouldn't work.

Categories

Resources