How to avoid calling the function

Asked

Viewed 537 times

4

I have in my systems a call for a function of and it always worked. It’s a function to display/hide an image by loading to the user. The problem is that sometimes I have to call this function in a user action from a field select, for example, and in case the user changes 10 times in a row this field select will make 10 calls, which is no problem, but it is bad for the user to keep appearing still the image because it keeps loading and disappearing 10 times.

Follow an example to better understand what I am saying.

In this case it is no action that it takes to execute, but because I have many ajax calls that may take a little longer, hence the need for me to display to the user who 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 on Jsfiddle

  • I wonder if I could show you the relevant code?

  • This is the link http://jsfiddle.net/QZ9q8/1/ of the entire @Tivie code

  • Thank you, I hadn’t seen

  • No crisis... if you change the select with the arrow keys is easier to understand.

  • 1

    A stop before fadein would resolve? http://jsfiddle.net/QZ9q8/2/

  • @bfavaretto resolves yes, lack a little knowledge even. Valew. Leave as an answer to can get better flagged right.

  • @bfavaretto wouldn’t be a stop at fadeOut?

  • I know it’s not the focus, but remember a better way to use the document.ready, using IIFE - Immediately Invoked Function Expression (English). Example here. Hug.

Show 3 more comments

2 answers

5


You can solve this easily by stopping the animation using .stop() before giving .fadeOut() and it might get even better if you also give a .stop() in the .fadeIn() also because I performed some tests and if you change too quickly you realize that the animation repeated once, so:

You were using fadeIn() and fadeOut() non-stop:

$('#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

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

Important detail about stop function():

The parameters of the function .stop() are to clear the queue of animations and also finish 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 must be completed immediately. (default false).

Example running on Jsfiddle

Reference

  • What does the false, true that you passed as parameter? I had thought of a stop in fadein because it would only have effect if there was already a fadeOut in progress.

  • @Paulo, tell me one thing, in this case what is the difference in you. And from what I could see in fadeOut it didn’t work

  • And what worked best was $('#ajaxLoadAni'). stop( true, true ).fadein('slow');

  • edited the answer explaining you @bfavaretto

  • beauty @Marcelodiniz thanks for the tip, I noticed this too, I changed the answer there ;)

  • Another thing @Marcelodiniz realized that using both in fadein and fadeOut also looks better.

  • 1

    Thanks, now I get it.

Show 2 more comments

3

Question of the PO:

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

  • User selects an option from the menu
  • The loading image is enabled
  • An AJAX request is made
  • In AJAX’s Success callback the loading image is disabled

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

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

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

  2. Use show() and hide() instead of fadeIn and fadeOut. It stops being animated and becomes instantaneous.

Another way, a little more complex would be to listen the ajaxStop event. This event is triggered when there are no more AJAX requests on the stack.

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

Thus, it is only when all the 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.


Problem of multiple requests:

However, assuming that the schematic I did of the steps of your application is correct, there is a bigger problem, which is the number of AJAX calls that can be fired almost simultaneously.

For example, if you use arrows to change the select and press the top and bottom button alternately 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 orders:

The simplest (and cleanest) solution would be to add a button that calls the function that makes the AJAX request, instead of listening to the "change" Event do "select"

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

You can also disable select while the ajax request is not finished, but this may make the user experience worse.

Another way to keep the interface as it is would be to put a "flag" that would prevent multiple AJAX requests from firing at the same time and only when the previous one was resolved would it 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 unincronizes the select menu, that is, if I change the option quickly, it will ignore the second option and only show the first one, although in the select menu it selects the second.

You also have the option to delay between selecting and requesting ajax.

  • That’s almost what you described. Now come on: I could have even put "fast" (so much so that in the real function my this as parameter, only left as clean as possible) but I did not leave because the interesting since it is an ajax call was preferable to leave in the same slow, and also could use the show and Hide, but in the same way was chosen to have the animation. And yes, it can happen to have the 2500 calls, unfortunately if you have something for that tbm help. And Valew even by the comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.