Comment retarder le gestionnaire .keyup () jusqu'à ce que l'utilisateur arrête de taper?

643

J'ai un champ de recherche. En ce moment, il recherche chaque touche. Donc, si quelqu'un tape «Windows», il effectuera une recherche avec AJAX pour chaque touche: «W», «Wi», «Win», «Wind», «Windo», «Window», «Windows».

Je veux avoir un délai, donc il ne recherche que lorsque l'utilisateur arrête de taper pendant 200 ms.

Il n'y a pas d'option pour cela dans la keyupfonction, et j'ai essayé setTimeout, mais cela n'a pas fonctionné.

Comment puis je faire ça?

ajsie
la source
4
Duplicate de stackoverflow.com/questions/1620602/…
Roatin Marth
2
Si je le pouvais, je fermerais cela en double.
a432511
7
Je ne vois pas le mal d'avoir des doublons, tant que les réponses données et acceptées sont correctes. L'ajout à la base de données de questions doit être quelque chose de bon et quelque chose à rechercher.
Mattis
14
Le mal est que les gens à l'avenir ne pourront pas bénéficier des réponses brillantes que tout le monde partage s'il y a 100 de la même question, donc fermer les dupes et rediriger tout le monde vers la question d'origine est préférable pour trouver les meilleures pratiques et les correctifs. Voir stackoverflow.com/help/duplicates pour plus d'informations sur les raisons de la fermeture des doublons.
rncrtr
14
C'est beaucoup plus populaire que celui qu'il était censé reproduire. Il est mieux formulé, il a de meilleures réponses, se classe plus haut sur Google, etc. Beaucoup ont bénéficié de cette réponse. Rétrospectivement, il aurait été dommage que cela soit clos. Il y en a quelques-uns triviaux qui sont mauvais comme doublons, mais cela ne tombe pas dans cette catégorie.
utilisateur

Réponses:

1124

J'utilise cette petite fonction dans le même but, en exécutant une fonction après que l'utilisateur a arrêté de taper pendant une durée spécifiée ou lors d'événements qui se déclenchent à un rythme élevé, comme resize:

function delay(callback, ms) {
  var timer = 0;
  return function() {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      callback.apply(context, args);
    }, ms || 0);
  };
}


// Example usage:

$('#input').keyup(delay(function (e) {
  console.log('Time elapsed!', this.value);
}, 500));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="input">Try it:
<input id="input" type="text" placeholder="Type something here..."/>
</label>

Comment ça fonctionne:

La delayfonction renverra une fonction encapsulée qui gère en interne un minuteur individuel, à chaque exécution le minuteur est redémarré avec le délai prévu, si plusieurs exécutions se produisent avant ce temps, le minuteur se réinitialise et recommence.

Lorsque le temporisateur se termine enfin, la fonction de rappel est exécutée, en passant le contexte et les arguments d'origine (dans cet exemple, l'objet événement jQuery et l'élément DOM as this).

MISE À JOUR 2019-05-16

J'ai ré-implémenté la fonction en utilisant les fonctionnalités ES5 et ES6 pour les environnements modernes:

function delay(fn, ms) {
  let timer = 0
  return function(...args) {
    clearTimeout(timer)
    timer = setTimeout(fn.bind(this, ...args), ms || 0)
  }
}

L'implémentation est couverte par un ensemble de tests .

Pour quelque chose de plus sophistiqué, jetez un œil au plugin jQuery Typewatch .

CMS
la source
64
Une autre alternative: github.com/bgrins/bindWithDelay/blob/master/bindWithDelay.js . Il fonctionne à peu près de la même manière que vous l'avez décrit, je viens de me retrouver à utiliser ce modèle beaucoup, donc je l'ai implémenté en tant que plugin jQuery pour simplifier la syntaxe. Voici une page de démonstration: briangrinstead.com/files/bindWithDelay
Brian Grinstead
2
j'ai initialement codé en dur le nombre de lettres tapées, cette approche est lisse comme de la mélasse (sans sulfer)
Har
2
Lorsque j'utilise ceci avec un $ .post (), il envoie tout ce qui a été tapé en même temps, mais il l'envoie autant de fois que j'avais une touche. Existe-t-il un moyen d'envoyer UNIQUEMENT lorsque le délai est écoulé?
ntgCleaner
7
Mais cela ne fonctionne pas si j'appelle deux ou plusieurs fonctions différentes qui nécessitent un retard individuel. J'ai fait cette solution à la place stackoverflow.com/a/30503848/1834212
Miguel
4
Je recommande le plugin 'bindWithDelay' lié dans le premier commentaire. Mais je suggère la réponse de @ Hazerider à cette question (ci-dessous - stackoverflow.com/a/19259625/368896 ), qui est meilleure que cette réponse et mérite d'être étudiée pour comprendre l'idée derrière une liaison simple et lisse pour permettre différents temporisateurs pour différents éléments - le même principe utilisé dans le code du plugin ci-dessus, mais plus facile à comprendre.
Dan Nissenbaum
60

Si vous souhaitez rechercher une fois le type terminé, utilisez une variable globale pour maintenir le délai d'expiration renvoyé par votre setTimoutappel et annulez-le avec un clearTimeouts'il ne s'est pas encore produit afin qu'il ne déclenche le délai d'expiration que lors du dernier keyupévénement.

var globalTimeout = null;  
$('#id').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
}   
function SearchFunc(){  
  globalTimeout = null;  
  //ajax code
}

Ou avec une fonction anonyme:

var globalTimeout = null;  
$('#id').keyup(function() {
  if (globalTimeout != null) {
    clearTimeout(globalTimeout);
  }
  globalTimeout = setTimeout(function() {
    globalTimeout = null;  

    //ajax code

  }, 200);  
}   
RHicke
la source
39

Une autre légère amélioration de la réponse de CMS. Pour permettre facilement des retards distincts, vous pouvez utiliser les éléments suivants:

function makeDelay(ms) {
    var timer = 0;
    return function(callback){
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
};

Si vous souhaitez réutiliser le même délai, faites simplement

var delay = makeDelay(250);
$(selector1).on('keyup', function() {delay(someCallback);});
$(selector2).on('keyup', function() {delay(someCallback);});

Si vous voulez des délais séparés, vous pouvez le faire

$(selector1).on('keyup', function() {makeDelay(250)(someCallback);});
$(selector2).on('keyup', function() {makeDelay(250)(someCallback);});
Paschover
la source
1
Il est intéressant de noter que la solution avec plus de 600 votes positifs au jour où j'écris ce commentaire n'est pas aussi bonne que cette réponse avec seulement 2 votes positifs (y compris le mien). Clairement supérieur, car il prend en charge plusieurs widgets qui peuvent partager ou non le retard. Excellente réponse.
Dan Nissenbaum
... Bien que le plugin jQuery dans le commentaire sous la réponse gère également des minuteries distinctes pour des éléments distincts, et ajoute également un argument de limitation et d'événement: github.com/bgrins/bindWithDelay/blob/master/bindWithDelay.js. L'approche générale de ce plugin est la même que votre code, donc votre code mérite d'être étudié attentivement afin de le comprendre pour sa simplicité avant d'essayer de comprendre le plugin le plus sophistiqué. Je recommande ce plugin, cependant - mais si vous n'avez pas besoin d'accélérer ou de transmettre des données d'événement, votre code est génial! Deux bonnes options. Merci!
Dan Nissenbaum
1
Hmm, cela retarde pour moi mais someApiCallse déclenche toujours plusieurs fois - maintenant juste avec la valeur finale du champ de saisie.
Roelant
30

Vous pouvez également regarder underscore.js , qui fournit des méthodes utilitaires comme debounce :

var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);
meleyal
la source
La même chose est également disponible dans Lodash - lodash.com/docs/#debounce
Adarsh ​​Madrecha
14

Sur la base de la réponse de CMS, j'ai fait ceci:

Mettez le code ci-dessous après inclure jQuery:

/*
 * delayKeyup
 * http://code.azerti.net/javascript/jquery/delaykeyup.htm
 * Inspired by CMS in this post : http://stackoverflow.com/questions/1909441/jquery-keyup-delay
 * Written by Gaten
 * Exemple : $("#input").delayKeyup(function(){ alert("5 secondes passed from the last event keyup."); }, 5000);
 */
(function ($) {
    $.fn.delayKeyup = function(callback, ms){
        var timer = 0;
        $(this).keyup(function(){                   
            clearTimeout (timer);
            timer = setTimeout(callback, ms);
        });
        return $(this);
    };
})(jQuery);

Et utilisez simplement comme ceci:

$('#input').delayKeyup(function(){ alert("5 secondes passed from the last event keyup."); }, 5000);

Attention: la variable $ (this) dans la fonction passée en paramètre ne correspond pas à l'entrée

Gaten
la source
12

Retarder les appels multifonctions à l'aide d'étiquettes

C'est la solution avec laquelle je travaille. Cela retardera l'exécution sur TOUTE fonction que vous souhaitez . Il peut s'agir de la requête de recherche par enfoncement, peut-être du clic rapide sur les boutons précédent ou suivant (qui autrement enverrait plusieurs demandes si on cliquait rapidement en continu et ne serait pas utilisé après tout). Celui-ci utilise un objet global qui stocke chaque heure d'exécution et le compare à la demande la plus récente.

Le résultat est donc que seul ce dernier clic / action sera réellement appelé, car ces demandes sont stockées dans une file d'attente, qu'après les X millisecondes est appelée si aucune autre demande avec le même label n'existe dans la file d'attente!

function delay_method(label,callback,time){
    if(typeof window.delayed_methods=="undefined"){window.delayed_methods={};}  
    delayed_methods[label]=Date.now();
    var t=delayed_methods[label];
    setTimeout(function(){ if(delayed_methods[label]!=t){return;}else{  delayed_methods[label]=""; callback();}}, time||500);
  }

Vous pouvez définir votre propre temps de retard (optionnel, 500 ms par défaut). Et envoyez vos arguments de fonction de façon "fermée".

Par exemple, si vous souhaitez appeler la fonction ci-dessous:

function send_ajax(id){console.log(id);}

Pour empêcher plusieurs demandes send_ajax, vous les retardez en utilisant:

delay_method( "check date", function(){ send_ajax(2); } ,600);

Chaque demande qui utilise le libellé "date de vérification" ne sera déclenchée que si aucune autre demande n'est effectuée dans le délai de 600 millisecondes. Cet argument est facultatif

Indépendance des étiquettes (appelant la même fonction cible) mais exécutez les deux:

delay_method("check date parallel", function(){send_ajax(2);});
delay_method("check date", function(){send_ajax(2);});

Entraîne l'appel de la même fonction mais les retarde indépendamment car leurs étiquettes sont différentes

Miguel
la source
J'utilise votre code dans un projet sur lequel je travaille et j'ai des difficultés avec lui. Cela ne retarde en fait rien. J'ai pensé que vous voudriez peut-être voir / fournir de l'aide. stackoverflow.com/questions/51393779/…
KDJ
10

Si quelqu'un aime retarder la même fonction, et sans variable externe, il peut utiliser le script suivant:

function MyFunction() {

    //Delaying the function execute
    if (this.timer) {
        window.clearTimeout(this.timer);
    }
    this.timer = window.setTimeout(function() {

        //Execute the function code here...

    }, 500);
}
Roy Shoa
la source
1
Génial! Solution facile qui fonctionne bien!
Fellipe Sanches
1
J'aime celui la. Pas exactement réutilisable mais facile à comprendre.
Vincent
10

Approche super simple, conçue pour exécuter une fonction après qu'un utilisateur a fini de taper dans un champ de texte ...

<script type="text/javascript">
$(document).ready(function(e) {
    var timeout;
    var delay = 2000;   // 2 seconds

    $('.text-input').keyup(function(e) {
        console.log("User started typing!");
        if(timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(function() {
            myFunction();
        }, delay);
    });

    function myFunction() {
        console.log("Executing function for user!");
    }
});
</script>

<textarea name="text-input" class="text-input"></textarea>
HoldOffHunger
la source
1
Je vous remercie! Les réponses populaires ci-dessus n'ont pas fonctionné ... mais votre suggestion a parfaitement fonctionné.
user2662680
1
2020 fonctionne toujours
Romel Indemne
7

Cette fonction étend un peu la fonction de la réponse de Gaten afin de récupérer l'élément:

$.fn.delayKeyup = function(callback, ms){
    var timer = 0;
    var el = $(this);
    $(this).keyup(function(){                   
    clearTimeout (timer);
    timer = setTimeout(function(){
        callback(el)
        }, ms);
    });
    return $(this);
};

$('#input').delayKeyup(function(el){
    //alert(el.val());
    // Here I need the input element (value for ajax call) for further process
},1000);

http://jsfiddle.net/Us9bu/2/

fazzyx
la source
6

Je suis surpris que personne ne mentionne le problème des entrées multiples dans le CMS très bien coupé.

Fondamentalement, vous devez définir une variable de retard individuellement pour chaque entrée. Sinon, si sb met du texte à la première entrée et passe rapidement à une autre entrée et commence à taper, le rappel de la première NE SERA PAS appelé!

Voir le code ci-dessous que je suis venu avec basé sur d'autres réponses:

(function($) {
    /**
     * KeyUp with delay event setup
     * 
     * @link http://stackoverflow.com/questions/1909441/jquery-keyup-delay#answer-12581187
     * @param function callback
     * @param int ms
     */
    $.fn.delayKeyup = function(callback, ms){
            $(this).keyup(function( event ){
                var srcEl = event.currentTarget;
                if( srcEl.delayTimer )
                    clearTimeout (srcEl.delayTimer );
                srcEl.delayTimer = setTimeout(function(){ callback( $(srcEl) ); }, ms);
            });

        return $(this);
    };
})(jQuery);

Cette solution conserve la référence setTimeout dans la variable delayTimer de l'entrée. Il transmet également la référence de l'élément au rappel comme suggéré par fazzyx.

Testé dans IE6, 8 (comp - 7), 8 et Opera 12.11.

jszoja
la source
J'ai essayé cela mais je n'arrive pas à travailler correctement sur la première touche.
Lars Thorén
6

Cela a fonctionné pour moi où je retarde l'opération de logique de recherche et vérifie si la valeur est la même que celle entrée dans le champ de texte. Si la valeur est la même, je continue et j'exécute l'opération pour les données liées à la valeur de recherche.

$('#searchText').on('keyup',function () {
    var searchValue = $(this).val();
    setTimeout(function(){
        if(searchValue == $('#searchText').val() && searchValue != null && searchValue != "") {
           // logic to fetch data based on searchValue
        }
        else if(searchValue == ''){
           // logic to load all the data
        }
    },300);
});
Sagar Gala
la source
ne fonctionne pas comme prévu - le nombre de récupérations est le même, juste retardé de 300 ms - vous devez utiliser la fonction clearTimeout () à chaque frappe, avant d'exécuter setTimeout ()
Picard
Eh bien, vous n'avez pas besoin d'utiliser clearTimeout dans ce cas. La condition searchValue == $ ('# searchText'). Val () dans setTimeout garantira que la valeur est la même que celle d'il y a 300 ms. Faites-moi savoir si cela a du sens. Merci.
Gala Sagar du
4

Fonction de délai pour appeler à chaque touche. jQuery 1.7.1 ou supérieur requis

jQuery.fn.keyupDelay = function( cb, delay ){
  if(delay == null){
    delay = 400;
  }
  var timer = 0;
  return $(this).on('keyup',function(){
    clearTimeout(timer);
    timer = setTimeout( cb , delay );
  });
}

Usage: $('#searchBox').keyupDelay( cb );

Vinay Aggarwal
la source
3

Il s'agit d'une solution similaire à celle des CMS, mais elle résout quelques problèmes clés pour moi:

  • Prend en charge plusieurs entrées, les retards peuvent s'exécuter simultanément.
  • Ignore les événements clés qui n'ont pas changé la valeur (comme Ctrl, Alt + Tab).
  • Résout une condition de concurrence critique (lorsque le rappel est exécuté et que la valeur a déjà été modifiée).
var delay = (function() {
    var timer = {}
      , values = {}
    return function(el) {
        var id = el.form.id + '.' + el.name
        return {
            enqueue: function(ms, cb) {
                if (values[id] == el.value) return
                if (!el.value) return
                var original = values[id] = el.value
                clearTimeout(timer[id])
                timer[id] = setTimeout(function() {
                    if (original != el.value) return // solves race condition
                    cb.apply(el)
                }, ms)
            }
        }
    }
}())

Usage:

signup.key.addEventListener('keyup', function() {
    delay(this).enqueue(300, function() {
        console.log(this.value)
    })
})

Le code est écrit dans un style que j'apprécie, vous devrez peut-être ajouter un tas de points-virgules.

À retenir:

  • Un identifiant unique est généré en fonction de l'identifiant du formulaire et du nom d'entrée, ils doivent donc être définis et uniques, sinon vous pouvez l'ajuster à votre situation.
  • delay renvoie un objet facile à étendre pour vos propres besoins.
  • L'élément d'origine utilisé pour le délai est lié au rappel, il thisfonctionne donc comme prévu (comme dans l'exemple).
  • La valeur vide est ignorée dans la deuxième validation.
  • Attention à la mise en file d' attente , elle attend d'abord des millisecondes, je préfère cela, mais vous voudrez peut-être changer les paramètres pour correspondre setTimeout.

La solution que j'utilise ajoute un autre niveau de complexité, vous permettant d'annuler l'exécution, par exemple, mais c'est une bonne base sur laquelle s'appuyer.

Jaime Gómez
la source
3

La combinaison de la réponse CMS avec celle de Miguel donne une solution robuste permettant des retards simultanés.

var delay = (function(){
    var timers = {};
    return function (callback, ms, label) {
        label = label || 'defaultTimer';
        clearTimeout(timers[label] || 0);
        timers[label] = setTimeout(callback, ms);
    };
})();

Lorsque vous devez retarder différentes actions indépendamment, utilisez le troisième argument.

$('input.group1').keyup(function() {
    delay(function(){
        alert('Time elapsed!');
    }, 1000, 'firstAction');
});

$('input.group2').keyup(function() {
    delay(function(){
        alert('Time elapsed!');
    }, 1000, '2ndAction');
});
Frédéric
la source
3

S'appuyant sur la réponse de CMS, voici une nouvelle méthode de retard qui préserve «ceci» dans son utilisation:

var delay = (function(){
  var timer = 0;
  return function(callback, ms, that){
    clearTimeout (timer);
    timer = setTimeout(callback.bind(that), ms);
  };
})();

Usage:

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000, this);
});
mga911
la source
2

Utilisation

mytimeout = setTimeout( expression, timeout );

où expression est le script à exécuter et timeout est le temps d'attente en millisecondes avant qu'il s'exécute - cela ne fait pas obstacle au script, mais retarde simplement l'exécution de cette partie jusqu'à ce que le timeout soit terminé.

clearTimeout(mytimeout);

réinitialisera / effacera le délai afin qu'il n'exécute pas le script dans l'expression (comme une annulation) tant qu'il n'a pas encore été exécuté.

Mark Schultheiss
la source
2

Basé sur la réponse du CMS, il ignore simplement les événements clés qui ne changent pas de valeur.

var delay = (function(){
    var timer = 0;
    return function(callback, ms){
      clearTimeout (timer);
      timer = setTimeout(callback, ms);
    };
})(); 

var duplicateFilter=(function(){
  var lastContent;
  return function(content,callback){
    content=$.trim(content);
    if(content!=lastContent){
      callback(content);
    }
    lastContent=content;
  };
})();

$("#some-input").on("keyup",function(ev){

  var self=this;
  delay(function(){
    duplicateFilter($(self).val(),function(c){
        //do sth...
        console.log(c);
    });
  }, 1000 );


})
Anderson
la source
1

Utilisez le plugin bindWithDelay jQuery:

element.bindWithDelay(eventType, [ eventData ], handler(eventObject), timeout, throttle)
Vebjorn Ljosa
la source
1
var globalTimeout = null;  
$('#search').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
});
function SearchFunc(){  
  globalTimeout = null;  
  console.log('Search: '+$('#search').val());
  //ajax code
};
krut1
la source
1

Voici une suggestion que j'ai écrite qui prend en charge les entrées multiples dans votre formulaire.

Cette fonction récupère l'objet du champ de saisie, inséré dans votre code

function fieldKeyup(obj){
    //  what you want this to do

} // fieldKeyup

Ceci est la fonction delayCall réelle, prend en charge plusieurs champs d'entrée

function delayCall(obj,ms,fn){
    return $(obj).each(function(){
    if ( typeof this.timer == 'undefined' ) {
       // Define an array to keep track of all fields needed delays
       // This is in order to make this a multiple delay handling     
          function
        this.timer = new Array();
    }
    var obj = this;
    if (this.timer[obj.id]){
        clearTimeout(this.timer[obj.id]);
        delete(this.timer[obj.id]);
    }

    this.timer[obj.id] = setTimeout(function(){
        fn(obj);}, ms);
    });
}; // delayCall

Usage:

$("#username").on("keyup",function(){
    delayCall($(this),500,fieldKeyup);
});
egpo
la source
1

Depuis ES6 , on peut également utiliser la syntaxe de la fonction flèche .

Dans cet exemple, le code retarde l' keyupévénement pendant 400 ms une fois que les utilisateurs ont fini de taper avant d'appeler, searchFunceffectuez une requête.

const searchbar = document.getElementById('searchBar');
const searchFunc = // any function

// wait ms (milliseconds) after user stops typing to execute func
const delayKeyUp = (() => {
    let timer = null;
    const delay = (func, ms) => {
        timer ? clearTimeout(timer): null
        timer = setTimeout(func, ms)
    }
    return delay
})();

searchbar.addEventListener('keyup', (e) => {
    const query = e.target.value;
    delayKeyUp(() => {searchFunc(query)}, 400);
})
Dat Nguyen
la source
1

jQuery :

var timeout = null;
$('#input').keyup(function() {
  clearTimeout(timeout);
  timeout = setTimeout(() => {
      console.log($(this).val());
  }, 1000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<input type="text" id="input" placeholder="Type here..."/>

Javascript pur:

let input = document.getElementById('input');
let timeout = null;

input.addEventListener('keyup', function (e) {
    clearTimeout(timeout);
    timeout = setTimeout(function () {
        console.log('Value:', input.value);
    }, 1000);
});
<input type="text" id="input" placeholder="Type here..."/>

Ali Nasr
la source
0

Jetez un œil au plugin de saisie semi - automatique . Je sais que cela vous permet de spécifier un délai ou un nombre minimum de caractères. Même si vous ne finissez pas par utiliser le plugin, parcourir le code vous donnera quelques idées sur la façon de l'implémenter vous-même.

tvanfosson
la source
0

Eh bien, j'ai également créé un morceau de code pour la cause de la demande d'ajax haute fréquence limite par Keyup / Keydown. Regarde ça:

https://github.com/raincious/jQueue

Faites votre requête comme ceci:

var q = new jQueue(function(type, name, callback) {
    return $.post("/api/account/user_existed/", {Method: type, Value: name}).done(callback);
}, 'Flush', 1500); // Make sure use Flush mode.

Et liez un événement comme celui-ci:

$('#field-username').keyup(function() {
    q.run('Username', this.val(), function() { /* calling back */ });
});

la source
0

J'ai vu cela un peu tard aujourd'hui, mais je veux juste le mettre ici au cas où quelqu'un d'autre aurait besoin. séparez simplement la fonction pour la rendre réutilisable. le code ci-dessous attendra 1/2 seconde après avoir tapé stop.

    var timeOutVar
$(selector).on('keyup', function() {

                    clearTimeout(timeOutVar);
                    timeOutVar= setTimeout(function(){ console.log("Hello"); }, 500);
                });
chungtinhlakho
la source
0

Bibliothèque utilisateur javascript lodash et utilisation de la fonction _.debounce

changeName: _.debounce(function (val) {
  console.log(val)                
}, 1000)
Amir Ur Rehman
la source
0
// Get an global variable isApiCallingInProgress

//  check isApiCallingInProgress 
if (!isApiCallingInProgress) {
// set it to isApiCallingInProgress true
      isApiCallingInProgress = true;

      // set timeout
      setTimeout(() => {
         // Api call will go here

        // then set variable again as false
        isApiCallingInProgress = false;     
      }, 1000);
}
Bharat chaudhari
la source