How to avoid function calls

4

I have a call on my systems for a and it always worked. It is a function to show / hide a loading image for the user. The problem is that sometimes I have to call this function in a user action of a select field, for example, and if the user stays 10 times in a row this select field will make 10 calls, which has no problems, but it is bad for the user to still appear the image because it is loading and disappearing 10 times.

Here's an example for a better understanding of what I'm saying.

In this case it is not an action that takes time to execute, but because I have many ajax calls that can take a little longer, hence the need for me to display to the user that is loading.

My code:

$(document).ready(function() {  
     $("select[name=meuSelect]").change(function(event) {
         event.preventDefault();

         var valor = $(this).val();

         ajaxLoadAni('In');     
         $("#valor").text(valor);     
         ajaxLoadAni('Out');
     });
});


function ajaxLoadAni(inOut) {
    'use strict';

    if (inOut === 'In') {
      $('#ajaxLoadAni').fadeIn('slow'); //EXIBE A IMAGEM DE CARRREGANDO
    } else {
        $('#ajaxLoadAni').fadeOut('slow'); //ESCONDE A IMAGEM DE CARRREGANDO
    }
}

Example running in JSFiddle

    
asked by anonymous 13.03.2014 / 14:57

2 answers

5

You can easily solve this by stopping the animation using .stop() before giving .fadeOut() and it can be even better if you also give .stop() to .fadeIn() also because I performed some tests and if you change very fast you notice that the animation has been repeated once, so:

You were using fadeIn() and fadeOut() without stopping:

$('#ajaxLoadAni').fadeIn('slow'); //EXIBE A IMAGEM DE CARRREGANDO
$('#ajaxLoadAni').fadeOut('slow'); //ESCONDE A IMAGEM DE CARRREGANDO

Adding a stop would look like this:

$('#ajaxLoadAni').stop(true,true).fadeIn('slow'); //EXIBE A IMAGEM DE CARRREGANDO    
$('#ajaxLoadAni').stop(true,true).fadeOut('slow'); //ESCONDE A IMAGEM DE CARRREGANDO

In this way you will stop the previous animation before leaving, thus not having to show / hide several times for the user.

Important detail about the stop () function:

The parameters of the .stop() function serve to clear the queue of animations and also finalize them, which would be:

  

stop ([clearQueue], [jumpToEnd])

     

[clearQueue] - Case true , indicates that the animation should be removed from the queue (default false ).    [jumpToEnd] - Case true , indicates that the animation should be completed immediately.

Example running in JSFiddle

Reference

    
13.03.2014 / 15:18
3

OP question:

As I understand it, the steps of its application (in a real context) are as follows:

  • User selects an option from the menu
  • The loading image is enabled
  • A request is made for AJAX
  • In AJAX's success callback the loading image is disabled

Your problem is that sometimes the user changes the selection more quickly than the animation.

In terms of user experience, it has some relatively simple solutions ...

  • Accelerate the animation. Instead of "slow" use "fast" or specify the milliseconds directly (slow is 600ms, fast is 200ms)

  • Use show() and hide() instead of fadeIn and fadeOut . It stops being animated and happens to be instantaneous.

  • Another, more complex way is to listen the ajaxStop event . This event fires when there are no more AJAX requests on the stack.

    $( document ).ajaxStop(function() {
        ajaxLoadAni('Out');
    });
    

    So, it's only when all ajax requests are finished that the animation is hidden. If you combine this with one of the solutions I presented or the suggestion suggested by Paulo Roberto, the user experience improves.

    Multiple order problem:

    However, assuming that the schematization I made of the steps in your application is correct, there is a bigger problem, which is the number of AJAX calls that can be triggered almost simultaneously.

    For example, if you use the arrows to change the select and alternately press the up and down keys 25 times, you will have 25 almost simultaneous AJAX requests in a very short space of time. If you do it 2500 times ... imagine.

    Solution to the problem of multiple requests:

    The simplest (and cleanest) solution would be to add a button that calls the function that does the AJAX request, instead of listening to the " change " event of in> "

    $('.ajaxBtn').click(function () {
        //Chamar ajax aqui
    });
    

    You can also disable select while the ajax request has not been completed, but this can worsen the user experience.

    Another way to keep the interface as it is would be to place a flag that would prevent multiple AJAX requests from firing at the same time and only when the previous one was resolved would you accept a new one.

     var ajaxFlag = false;
     $("select[name=meuSelect]").change(function(event) {
         event.preventDefault();
    
         var valor = $(this).val();
         if (ajaxFlag === false) {
             ajaxLoadAni('In');
             ajaxFlag = true;
             //Funcao AJAX
             $.ajax()
                .success(function() //Quando é bem sucessida
                {
                    $("#valor").text(valor);
                })
                //.error() //QUando dá erro
                .complete(function() //é sempre chamada
                {
                    ajaxLoadAni('Out');
                    ajaxFlag = false;
                })
            }       
     });
    

    The problem with this solution is that it desynchronizes the select menu, that is, if I quickly change the option, it will ignore the second option and show only the first one, although in the select menu you select the second one.

    You also have the option to delay between the selection and the ajax request.

        
    13.03.2014 / 15:26