111

I am looking for something like this

function someFunc() {

callAjaxfunc(); //may have multiple ajax calls in this function
someWait(); // some code which waits until async calls complete
console.log('Pass2');

}

function callAjaxfunc() {
  //All ajax calls called here
  console.log('Pass1');

}

What I have tried?

1 Jquery.when()

tried using it..it works fine. But not the way I want. $.when will wait but the code next to $.when() runs with out waiting. The code inside do callback only runs after ajax calls

2. setTimeOut() with a global flag

I was so confident this will work. I tried like following.

GlobalFlag = false;

function someFunc()     
    callAjaxfunc(); //may have multiple ajax calls in this function
    setTimeOut(waitFunc, 100); // some  which waits until async calls complete
    console.log('Pass2');
}

function callAjaxfunc() {
    //All ajax calls called here
    onAjaxSuccess: function() {
        GlobalFlag = true;
    };
    console.log('Pass1');    
}

function waitFunc() {
    if (!GlobalFlag) {
        setTimeOut(waitFunc, 100);
    }
}​

Still not able to get wanted result. Am I doing something wrong here? This is not the way?

Result I wanted should come like this

Pass1
Pass2

Not able to make any fiddle as it needs AJAX calls

EDIT: As many were suggesting callbacks..i know about them..but still the code next to somewait() will get executed...I want browser to completely stop executing code next to somewait() until the ajax call..Also it may be a bad practice but worth to know and try if possible...

thecodejack
  • 12,689
  • 10
  • 44
  • 59
  • FYI http://jsfiddle.net supports ajax testing. Can't you just move the code after the `someWait` to inside the `.then` callbacks? – Fabrício Matté Dec 25 '12 at 14:22
  • 2
    Use the callback function of the ajax call – Stefan Fandler Dec 25 '12 at 14:22
  • Using callbacks (`$.when`) is the only reasonable way to do this... – Felix Kling Dec 25 '12 at 15:09
  • i know about callbacks..thats the basic way...but here i want to stop browser to do anything..until Ajax calls finish. – thecodejack Dec 25 '12 at 16:15
  • @FabrícioMatté..how to add ajax calls??... – thecodejack Dec 25 '12 at 16:19
  • Since JavaScript is a single threaded language (Not including WebWorkers in browsers), putting such a synthetic wait logic will not only stop your JS from executing but will also lock all rendering in the browser. As people have suggested you should be using promises for such a behavior. Save yourself trouble and do not use callbacks as they become harder to maintain and create the pyramid of doom. – Gabriel Kohen May 25 '16 at 12:37

4 Answers4

63

Use callbacks. Something like this should work based on your sample code.

function someFunc() {

callAjaxfunc(function() {
    console.log('Pass2');
});

}

function callAjaxfunc(callback) {
    //All ajax calls called here
    onAjaxSuccess: function() {
        callback();
    };
    console.log('Pass1');    
}

This will print Pass1 immediately (assuming ajax request takes atleast a few microseconds), then print Pass2 when the onAjaxSuccess is executed.

Dogbert
  • 212,659
  • 41
  • 396
  • 397
  • 9
    i know about callbacks..thats the basic way...but here i want to stop browser to do anything..until Ajax calls finish.. – thecodejack Dec 25 '12 at 16:14
  • 2
    @CodeJack, I don't think that's possible in javascript. What exactly do you want to achieve by doing that, which can't be done this way? (i.e. moving code into a callback). – Dogbert Dec 25 '12 at 19:25
  • 3
    thing is am using some propreitory framework..there is load function where page starts loading and before page loads i need to get data and only function i can override is load function... – thecodejack Dec 26 '12 at 08:15
  • so load the data _before_ calling into the framework? Trying to make js block is a bad idea. It is technically possible using synchronous requests, but it is a terrible idea that should never be used. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests – Ajax Jan 16 '17 at 22:15
  • There can be situations where the callbacks are inappropriate, for example: ``webview.clearData({since: 0}, clearDataType, function(){ ... // recreate fresh webview });`` will pose a resource hog (chrome will create a new copy of local storage waiting until old one will be freed from references from inside callback which will never happen. – Vlad Jun 21 '18 at 16:46
  • Hi, I don't understand the syntax where you define onAjaxSuccess. It looks like the syntax for defining a method, but it's inside of a function that's not a constructor. What are we looking at here? Thanks! – David Kennell Sep 05 '18 at 20:05
23

Why didn't it work for you using Deferred Objects? Unless I misunderstood something this may work for you.

/* AJAX success handler */
var echo = function() {
    console.log('Pass1');
};

var pass = function() {
  $.when(
    /* AJAX requests */
    $.post("/echo/json/", { delay: 1 }, echo),
    $.post("/echo/json/", { delay: 2 }, echo),
    $.post("/echo/json/", { delay: 3 }, echo)
  ).then(function() {
    /* Run after all AJAX */
    console.log('Pass2');
  });
};​

See it here.


UPDATE

Based on your input it seems what your quickest alternative is to use synchronous requests. You can set the property async to false in your $.ajax requests to make them blocking. This will hang your browser until the request is finished though.

Notice I don't recommend this and I still consider you should fix your code in an event-based workflow to not depend on it.

Alexander
  • 23,432
  • 11
  • 63
  • 73
  • i tried using 'when'..but the way i want is i want browser to stop doing anything until Ajax call completes...and basically this code is during load... – thecodejack Dec 25 '12 at 16:17
  • @CodeJack, sorry to tell you but the browser shouldn't wait, **you** should wait – Alexander Dec 25 '12 at 16:30
  • 2
    @CodeJack, if you still want to go with it set [`async`](http://api.jquery.com/jQuery.ajax/) to `false` in the AJAX calls that you want to make blocking – Alexander Dec 25 '12 at 16:38
  • oh..there is property to set `async` to `false`...thanks..let me check on that..Thanks.. – thecodejack Dec 25 '12 at 16:46
  • @CodeJack, did it work better? – Alexander Dec 26 '12 at 14:24
  • browser hangs..but i think i have to deal with it..can u edit the answer...i will accept it... – thecodejack Dec 27 '12 at 04:48
  • @CodeJack, done. That was expected and that's why it's bad practice – Alexander Dec 27 '12 at 11:09
  • async to false is both deprecated and buggy and MUST be avoided unless you like a lot of headaches. Just go with the callback route – IcedDante Jul 25 '15 at 18:25
  • The problem with when is that I can't "return" from pass() on ajax completion. If I put "return" into the anonymous function in "done()" -- this return will exit that anonymous functiononly. If I put return after the whole "when()/done()" -- it won't wait until ajax requests completion. – pilat Aug 02 '16 at 10:01
  • @pilat, You comment tells me that you don't really understand how to work with asynchronous calls. You might want to read and play a bit more with it before jumping into more complex asynchronous/deferred constructs. – Alexander Aug 02 '16 at 12:33
  • @Alexander I believe I have some idea on async calls. What I do not (yet) know is how to overcome it. Here's the widgets API I'm trying to make widget for: you write a function(class) which returns(exposes) a set of callbacks: render, init, bint_actions, etc. Say, I need to load my data in "init", and use it in "bind_actions".It just feels right to me. How do I wrap several widget-api callbacks into one $.getJSON callback? – pilat Aug 04 '16 at 11:58
9

Real programmers do it with semaphores.

Have a variable set to 0. Increment it before each AJAX call. Decrement it in each success handler, and test for 0. If it is, you're done.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • 4
    semaphores is something available in programming languages not in JavaScript... – thecodejack Dec 25 '12 at 16:24
  • 2
    Semaphores like critical sections are techniques that permit secure sharing resources between thread/process. I think you are confused with the term. As @CodeJack say this kind of objects are no available in Javascript but if it would, they wouldn't be applicable in this case. – HMarioD Dec 25 '12 at 17:05
  • 2
    @HMarioD: I am confused? http://en.wikipedia.org/wiki/Asynchronous_semaphore - particularly note that *all of the examples are in JavaScript*. – Amadan Dec 26 '12 at 00:12
  • 3
    @CodeJack: As my comment above mentions, semaphores are absolutely applicable to JavaScript. The concept that JavaScript does not have is a *lock*, due to the absence of concurrence. Semaphores are just glorified counters, often used in conjunction with locks (since in a multithreaded environment you absolutely need them). – Amadan Dec 26 '12 at 00:14
  • @Amadan you are right, you are not confused with the term, sorry. In fact Javascript don't have semaphores but you can construct semaphores like structures. Anyway I still think they are no applicable in that case. I'm C/C++ programmer mainly programming embedded devices running RTOS and communicating them with services in Linux boxes running tons of threads sharing comm ports an DB connections, then my vision of semaphores is very different. BTW I don't down vote you but in my opinion the -2 are more related with the answer title than the technical recommendation on it. :) – HMarioD Dec 26 '12 at 12:53
  • 1
    @HMarioD: Could be :) It combines two old jokes though ([one](http://www.dkgoodman.com/doita-f.html) [two](http://www.multicians.org/thvv/realprogs.html)), was funny to me. – Amadan Dec 26 '12 at 15:26
  • Very funny especially the two. – HMarioD Dec 26 '12 at 16:00
  • Although I wouldn't do it this way, +1 for thinking out of the box. This is a compelling, and sometimes forgotten, technique. – Throoze Nov 13 '15 at 14:16
0

If you need wait until the ajax call is completed all do you need is make your call synchronously.

HMarioD
  • 842
  • 10
  • 18
  • 9
    Bad practice in JS. – Trevor Dec 25 '12 at 14:38
  • 3
    Could you explain to me why make a synchronous call is a bad practice when that we need is make the call synchronic. Please. – HMarioD Dec 25 '12 at 14:42
  • 4
    Well, especially in this case of AJAX, you'll freeze the entire browser while they try to complete. JS runs in an event loop. You don't want to block unrelated code. – Trevor Dec 25 '12 at 14:46
  • 4
    @Trevor in some cases is necessary stop all until some action is performed or a timeout is reach, the original question of this post sugere some kind of synchronism between calls. I don't know the all picture of this case but I know that "god practices" must be reconsidered in each case in order to obtain the best result. Exist normalization but some kind of de-normalization some time is healthy. We are free to take our own decisions. Sorry my poor english and merry christmas. – HMarioD Dec 25 '12 at 15:17
  • @Trevor...as Mario suggested problem with mine is i am using a framework(internal one)...and here on load the call should go and browser should wait until the Ajax call finishes.. – thecodejack Dec 25 '12 at 16:19
  • Agree to disagree. :) Happy holidays – Trevor Dec 25 '12 at 17:23