I have some old code which I've now being asked to make asynchronous.
It's basically a jQuery GET function ... like this:
jQuery.get("my url", function(data){
//code here
});
How can I make this asynchronous?
By default jQuery.get is an asynchronous call , to make it synchronous you have to set it
jQuery.ajaxSetup({async:false});
Perhaps you mistyped your question—ajax calls are asynchronous by default, but here is how you would make it synchronous.
The best way would be to use the long-form ajax request (for which jQuery.get() is shorthand).
It would look like the following
jQuery.ajax({
method: "GET",
url: "my url",
async: false,
data: data,
success: function(data){},
});
The reason why jQuery.ajaxSetup({async:false}); is bad form is because it makes every ajax call synchronous, not just the individual call you want to change.
Related
Due to the (my perceived) nature of the $.ajax GET I'm not sure what I'm looking for is possible in this method, but thought I should ask as it's causing me some trouble. I am in no way an expert on JS, apologies if this is obvious, the title is poor, couldn't think of a different way to say it.
What I'm doing - using $.ajax to get values from the back-end API functions (these work). In the success property I'm using an anonymous function to pass more data across that would not otherwise be brought back. When stepping through the console breakpoints in the Chrome console the success function is often skipped as it's not brought back quick enough.
What I would like - in the example below, I don't want getStuff to complete, before its success DoSomething has returned, as I'm missing loads of data from the API which I need to pass through to DoSomething - is this possible to achieve?
Example
function getStuff(id, hid) {
$.ajax({
type: "GET",
url: "/api/GetMyStuff/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (vData) {
DoSomething(vData, id, hid); // not always being hit
}
});
}
You could use the async option and set it to false to get a synchronous call:
function getStuff(id, hid) {
$.ajax({
type: "GET",
url: "/api/GetMyStuff/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false, // HERE
success: function (vData) {
DoSomething(vData, id, hid); // not always being hit
}
});
}
But that is not a good way to do ajax request, you should rethink your code organization (like giving a callback function to your getStuff method and calling it in the success callback).
What you are trying to do is impossible. Asynchronicity is "leaky", meaning that any asynchronous action requiring a callback (e.g., $.ajax()) necessarily forces asynchronous control flow all the way up the call chain.
Please note that in the near future (thanks to async/await in ES7), this situation gets a little better. The asynchronicity is still leaky, but the new keywords make the refactoring scenario a little easier than hand-jamming callbacks everywhere.
I have a little question. say i have a js function
$(function() {
$(".button").click(function(){
var id=$(this).attr('id');
var dataString = 'id='+ id ;
$.ajax({
type: "POST",
url: "download_number.php",
data: dataString,
cache: false,
success: function(html)
{
$("#div_"+id).html(html);
} });
window.open('File_download.php?file_id='+id, '_blank' );
});
as you can see window.open call is after $.ajax call
Does it guaratee that $.ajax call will get executed every time before the page reloads and if no then
shouldn't we declare window.open in success function?
In my opinion when there is slow response from server the page will reload first and it may happen that $.ajax call will be interrupted by window.open function
but i get a downvote for the same reason here stackoverflow.com/questions/12908138/how-to-get-the-id-or-name-of-related-file/
And Thanks for making my belief stronger
In your example, the window.open function will always (!) be called before the success callback function given to the ajax call. Ajax traffic is always asynchronous, whereas the window.open function resides in the synchronous JS <script> tag.
Since JavaScript is single-threaded, all synchronous statements will always be executed before any asynchronous functionality like ajax setTimeout animate etc.
$.ajax({
type: "POST",
url: "download_number.php",
data: dataString,
cache: false,
success: function(html) { // asynchronous functionality
$("#div_"+id).html(html);
}
});
// within synchronous script statements
window.open('File_download.php', '_blank' );
Yes, Ajax is asynchronous so you will open that window right after you started the XHR process. To download the processed data, open the new window from the success callback. Yet I'm not sure what you mean by "before the page reloads" - there is no code which does that.
Also I don't know how your server behaves, the file_download.php seems to be independent from your ajax call. Shouldn't you pass the download_number you received via ajax in there?
This question already has answers here:
How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
(14 answers)
Closed 9 years ago.
I’ve been googling this and avoiding this error in my bug fix list for a long time now, but I’ve finally reached the end of the list, the last of which I have to make a function return true/false to state whether the validation has succeeded or not.
I'm using ajax to compare certain fields with those that are already in the db and by default the $.post() method does it's operations asynchronously.
I’m setting a variable inside the call onSuccess and the calling method doesn't get a response because of this, so all my js/jquery fails on pageLoad... I would prefer if I could still keep using the $.post method.
jQuery < 1.8
May I suggest that you use $.ajax() instead of $.post() as it's much more customizable.
If you are calling $.post(), e.g., like this:
$.post( url, data, success, dataType );
You could turn it into its $.ajax() equivalent:
$.ajax({
type: 'POST',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
Please note the async:false at the end of the $.ajax() parameter object.
Here you have a full detail of the $.ajax() parameters: jQuery.ajax() – jQuery API Documentation.
jQuery >=1.8 "async:false" deprecation notice
jQuery >=1.8 won't block the UI during the http request, so we have to use a workaround to stop user interaction as long as the request is processed. For example:
use a plugin e.g. BlockUI;
manually add an overlay before calling $.ajax(), and then remove it when the AJAX .done() callback is called.
Please have a look at this answer for an example.
If you want an synchronous request set the async property to false for the request. Check out the jQuery AJAX Doc
From the Jquery docs: you specify the async option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.
Here's what your code would look like if changed as suggested:
beforecreate: function(node,targetNode,type,to) {
jQuery.ajax({
url: url,
success: function(result) {
if(result.isOk == false)
alert(result.message);
},
async: false
});
}
this is because $.ajax is the only request type that you can set the asynchronousity for
function myobj(){
var gup=this;
this.lastindex=-1;
this.criticalSectionInTimer=0;
this.updateTimer;
this.start = function(l){
if((typeof this.updateTimer)=="number"){
clearInterval ( this.updateTimer );
}
this.updateTimer=setInterval(function() {gup.getMessages();} , 30);
}
this.stop= function(){
if((typeof this.updateTimer)=="number"){
clearInterval ( this.updateTimer );
}
}
this.addUpdate(i){
//some code
}
this.rrrrnr=0;
this.getMessages = function (){
if(this.criticalSection==0){
this.criticalSection=1;
this.rrrrnr++;
console.log("in critical section"+this.rrrrnr);
var url="getmessages.php?lastindex="+this.lastindex;
$.getJSON(url,
function(data){
gup.lastindex=data.lastindex;
$.each(data.updates, function(i,item){
gup.addUpdate(item);
});
}
);
console.log("out critical section"+this.rrrrnr);
this.criticalSection=0;
}
}
}
var m= new myobj();
myobj.start();
I have the code from above. I have a main loop which makes updates at a given time interval. The problem is i have realized that it is getting in the "critical section" which I have delimited by the variable this.criticalSection .
From firebug i get the messages "in critical section" + index and "out critical section" +index in the right order but the ajax request is still being processed. But I get request with the same index and i really don't know where to look for the problem.
Are there any buildin features for semaphores or critical sections in javascript?
There aren't semaphores or critical sections because JavaScript is single-threaded. The ajax call you make is asynchronous, so it kicks off the request and then happily keeps going and leaving your critical section. As others have mentioned, a simple solution is to make the request synchronous, but this defeats the purpose of ajax.
Looking at your code, it seems like you are trying to get updates at regular intervals. If this is the case, why not schedule the next update in the callback of the ajax request?
this.getMessages = function (){
var url="getmessages.php?lastindex="+this.lastindex;
$.getJSON(url,
function(data){
gup.lastindex=data.lastindex;
$.each(data.updates, function(i,item){
gup.addUpdate(item);
});
gup.updateTimer=setTimeout(gup.getMessages, 30);
}
);
}
This would remove the need for semaphores, and is more in line with the event-driven nature of JavaScript. The downside is the updates are not done at exact intervals. Also, 30 milliseconds seems an extremely short interval.
jQuery send AJAX Async by default. Insted of doing getJSON try:
$.ajax({
dataType: 'json',
url: url,
type: 'GET',
async: false,
success: function(data){
gup.lastindex=data.lastindex;
$.each(data.updates, function(i,item){
gup.addUpdate(item);
});
});
The proble is fairly simple.
You are using AJAX, which, by definition, is asynchronous. That means, you execute $.getJSON, and the js will continue and exit the critical section while the request is being processed. Therefore, several calls to getMessages can be performed before the first requests completes.
It seems that you intend such a getJSON call NOT not be async, and be blocked within the critical section until it ends. To do so, you must set the async property to false, something in the lines of:
$.ajax({
dataType: 'json',
url: "getmessages.php?lastindex="+this.lastindex,
type: 'GET',
async: false,
success: function(data){
gup.lastindex=data.lastindex;
$.each(data.updates, function(i,item){
gup.addUpdate(item);
});
});
Similar to the question I just asked,
If I call an ajax function in jQuery and then a non ajax function how can I prevent the non-ajax function from firing until after the first ajax callback function has completed. Will declaring async: false in the first ajax function be enough?
If you're talking about this:
$.ajax({...});
someFunction();
where someFunction() won't occur until the AJAX call completes then you have three options:
Make the AJAX call async: false. Don't do this. It'll make your page unresponsive;
Put someFunction() in the complete/success/error callbacks of the AJAX call. This is the recommended approach; or
Use aplugin to manage a request queue eg Ajax Queue.
The first A in AJAX stands for "asynchronous". You just need to get used to the fact that these calls are asynchronous and stop trying to force a synchronous programming model on top of them. Adapt to the new programming model.
jQuery AJAX functions let you provide a callback that is only called after the request is finished. Call your non-ajax function as part of that callback.
You can use callback functions like this:
$("#btnSample").on("click", function (e) {
$.ajax({
url: 'some_url',
type: "GET",
async: true,
cache: false,
dataType: "JSON",
data: {
"p1": v1,
"p2": v2
},
success: function(result) {
//call you second function here!
}
}
});
});