31 votes

Comment exécuter du code après que tous les autres événements ont été traités

J'ai un gestionnaire d'événements, mais je veux m'assurer qu'il attendra que tous les autres événements dans la file d'événements aient été exécutés.

Par exemple, j'ai des onglets sur une page. J'ai du code général pour gérer les onglets qui définit un onglet comme "Onglet actif" lorsque un utilisateur clique dessus.

$('a.tab').click(function() {
  $(this).parent('div').find('a.tab').removeClass('activeTab');
  $(this).addClass('activeTab');
});

Pour un ensemble spécifique d'onglets, je pourrais avoir un gestionnaire:

// gestionnaire-1
$('div#myTabs a.tab').click(function() {
  faire_quelque_chose();
});

function faire_quelque_chose() {
  var type = $('div#myTabs a.activeTab').data('type');
  faire_autre_chose(type);
}

faire_quelque_chose() pourrait être appelé en réponse à d'autres actions en dehors du clic sur un onglet, mais peu importe comment il est invoqué, il veut savoir quel est l'onglet actif avant de pouvoir continuer.

Mon problème est que s'il est invoqué par le code sous '// gestionnaire-1', la classe 'activeTab' n'a peut-être pas encore été réinitialisée, donc la valeur qu'il récupère pour 'type' sera toujours celle de whatever tag a été sélectionné avant de cliquer sur celui-ci.

J'ai résolu cela de cette manière:

// gestionnaire-1
$('div#myTabs a.tab').click(function() {
  set_timeout( function() {
    faire_quelque_chose();
  }, 100);
});

Cela semble être un peu trop astucieux pour moi. Comment savoir si le gestionnaire d'événements de temporisation sera appelé uniquement après que tous les autres gestionnaires auront eu leur tour? Bien sûr, je pourrais changer "100" à "1000" voire même à "10000" mais je sacrifierais également des performances pour plus de certitude (et il n'y a toujours aucune certitude, car même 10 secondes peuvent ne pas être suffisantes sur une instance de navigateur sur une machine assez endommagée).

J'ai vu plusieurs solutions possibles:

mais aucun de ceux-ci n'est assez général pour me satisfaire. Je n'essaie pas de faire en sorte qu'un gestionnaire s'exécute premier. Plutôt, je veux quelque chose comme ceci:

function faire_quelque_chose() {
  $.when_all_other_events_have_been_handled(function() {
    faire_quelque_chose();
  });
});

Est-ce que quelque chose comme cela existe?

J'ai regardé $.fn.when(arg).done(), mais quand quoi? "arg" dans ce cas devrait être un objet différé qui exécute ce qui se trouve déjà dans la file d'attente d'exécution. Un cercle vicieux!

Sproutcore a quelque chose comme "engine.run()" (je ne me souviens pas du nom exact) qui ne retournera que lorsque tous les autres événements dans le "moteur" auront été traités, mais je ne trouve rien de tel dans jQuery. (http://api.jquery.com/category/events/). Si quelqu'un connaît quelque chose de similaire, merci de me le faire savoir!

Merci! :)

33voto

c-smile Points 8609

Essayez ceci :

fonction reporter( fun )
{
  window.setTimeout(fun,0);
}

donc si vous appelez reporter(faire_quelque_chose); ce faire_quelque_chose sera exécuté après tous les événements d'interface utilisateur qui sont dans la file d'attente pour le moment de l'appel à reporter().

31voto

lsiden Points 1430

Je pourrais avoir trouvé la réponse ici : http://ejohn.org/blog/how-javascript-timers-work/

According to J. Resig, si je fais

setTimeout(function() {
  do_something();
}, 0);

la fonction anonyme sera enfilée immédiatement mais ne sera pas appelée tant que tout le reste dans la file d'événements n'aura pas déjà été traité. En effet, tant que le navigateur sur lequel elle s'exécute exécute vraiment tout sur une base de premier arrivé, premier servi comme je m'y attendrais. Si pour une raison quelconque le moteur JavaScript décide de réorganiser les événements dans la file (je ne vois pas pourquoi, mais on ne sait jamais car à ma connaissance je n'ai jamais vu de garantie de la sorte dans les normes, mais je dois vérifier de nouveau), alors tout est possible !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X