Call a function before synchronous call
Asked Answered
C

4

6

I have a simple question (but the answer does not seem to be simple).

I have a synchronous AJAX call in my code and I want to call a function before this synchronous call.

The function I want to call is simply

$.blockUI();

from jQuery BlockUI Plugin.

I simply tried to put that line before my $.ajax call but the blockUI seems to be called after the synchronous call.

I then tried to use the beforeSend option of $.ajax, same problem as above.

Thanks in advance for any answer you could bring (except using asynchronous call which is just impossible in my case...)

Code is available here : http://jsfiddle.net/vWsus/2/

Complemental answered 24/7, 2012 at 14:14 Comment(8)
could you post your code here or make a jsFiddle please?Daune
Have you tried just using: $(document).ajaxStart($.blockUI).ajaxStop($.unblockUI);Slick
If your are testing the code on your computer, the ajax call could be faster than the fadein. You could try to set the fadein to 0.Cowcatcher
By the way, synchronous ajax behavior including blocking user interaction tends to produce a terrible user interface experience. "As friendly as a cornered rat." Look into UI design patterns and books including "Don't make me think" to produce a much better experience for your users...Norseman
First of all, why do you need to block the UI for a synchronous AJAX (or SJAX, I guess) if it blocks the UI anyway? Second, why is an asynchronous call impossible in your case? Could you explain it a little bit? Also I'm sure that posting actual code examples would make it much easier to help you.Levee
@Slick Same problem again, the blockUI is shown AFTER my ajax call is completed...Complemental
@Levee In fact, I don't use blockUI to "block" the UI, I use it as a loading message. Actually, I am creating a design application in which user drags and drops items into a drop area and when an item is dropped, there is a heavy proccess that's why I would like to show a message saying it's in progress. I tried "blocking" the UI in the first line of the drop event of the droppable item but it does not work, the blockUI is shown after the call again ...Complemental
@user1374021: I think m.abbas is right (+1) that the problem may be the display reflow that is queued before but executed after the blocking function returns and I also agree with him that you should use an asynchronous AJAX call if you don't want to have that problem ("A" in AJAX stands for "asynchronous"). Also you didn't answer why an asynchronous call is impossible in your case. I have never seen such a case so that's why I am very interested to hear about yours.Levee
C
4

Synchronous calls are bad, they lock up the browser and if the call is not returned, it is not a good user experience. The problem you have is the synchronous call is locking up the browser so the DOM never has time to redraw. You need to give time for the DOM to update, so set a timeout before making the Ajax call.

$.blockUI({ message: '<p>foo</p>' });
window.setTimeout( ajxCallFnc, 100);
Composer answered 24/7, 2012 at 14:46 Comment(3)
I know synchronous calls are bad but I need to use it else I lose some data so setting a timeout on my ajax call is not an option. Trust me, I would love to use asynchronous calls but this time I cant...Complemental
@Complemental Solution still works, just have to give the blockui code time to run. Add a slight delay before you make the actual Ajax call.Composer
@user1374021: the solution by epascarello is doing a synchronous call, not asynchronous. Still, could you answer why do you say that you can't use asynchronous call and why do you think you'll lose some data doing so? There is a chance that you may be mistaken and that you in fact can use async call which would greatly simplify your problem. Otherwise if it is the case that you in fact can't use asynchronous call then I would love to know your use case because I haven't yet seen such a case. Surely either me or you will learn something if you care to answer my question. Thanks.Levee
K
1

In your case, it's not that the blockUI is called after the synchronous call, it's just that the synchronous request prevents the display reflow (which generally happens "sometimes later" than your actual DOM manipulation). And as you said, when you tried & called blockUI before the call to ajax rather than from inside the beforeSend callback, you end up with pretty much the same result.

There is nothing that can be done in jQuery to prevent this behaviour since it is not a jQuery bug (nor a browser one per se, seeing as synchronous xhr requests are supposed to freeze the browser anyway and that nothing says the browser has to carry on with the reflow in that instance).

All I can recommand is to NEVER EVER use synchronous requests. Asynchronous ones are easy enough to deal with.

You can take a look on Why You Should Use XMLHttpRequest Asynchronously

Kipp answered 24/7, 2012 at 14:54 Comment(0)
D
0

$.blockUI has a onBlock function. Try something like this:

$.blockUI({ 
    message: '<img id="processing" src="images/loading.gif" />', 
    onBlock: function() {
        // make your sync call here
        $.ajax({
            type: 'POST',
            cache: false,
            async: false,               
            url: blahblah,
            dataType: 'json'                
        }).done(function(data){
            //process response

        });
    }
}); 
Dichy answered 24/2, 2014 at 20:58 Comment(1)
At this point, your code is asynchronously executing when the onBlock() is called - meaning you might as well make your ajax call async since everything after the $.blockUI() call will execute before the response.Doublebank
N
0
this.notifyFixed=function(type,msg,callback){
        this.showNotification(type, msg);
            window.setTimeout(function(){
                if(typeof callback ==="function"){
                    callback();
                }
            },100);
    };

I had a notifyFixed function that I wanted to do before I make my ajax call, was running into same problems, so I added timeout and a callback function similar to epascarello that seemed to work fine for me.

So hopefully similar solution can help other people

Nathannathanael answered 12/8, 2014 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.