2009-07-02 5 views
1

Je construis un calendrier de concert très lourd en javascript (en utilisant jQuery). Je n'arrive pas à synchroniser divers événements dans l'application, et je cherche des suggestions sur la façon de procéder.Synchronisation d'événements Javascript

Un exemple d'un cas simple d'utilisation:

  1. utilisateur clique sur un mois
  2. Calendrier passe à ce mois

Un exemple d'une utilisation plus complexe cas:

  1. L'utilisateur sélectionne un artiste
  2. Le calendrier détermine t il date du premier spectacle
  3. Calendrier passe à ce mois
  4. Calendrier souligne que le spectacle de l'artiste (s)

Un problème occasionnel est que le nouveau mois n'a pas encore été rendu au moment de cet artiste je tente pour mettre en valeur le (s) spectacle (s) de l'artiste. Ainsi, le spectacle n'est pas mis en évidence même si ces fonctions sont appelées dans l'ordre. De toute évidence, l'utilisation de setTimeout() est assez hacky, et pas garanti pour fonctionner. Tout d'abord, une question simple: serait-il possible (même dans Chrome) que la fonction suivante ne fonctionne plus?

function steps(){ 

    stepOne(); //TAKES 30 SECONDS 

    stepTwo(); //TAKES < 1 SECOND 

} 

En second lieu, une simple question liée:

 
    If placed at the end of a function, will a JS callback ALWAYS run after 
    everything else in the given function has finished running? 

Si oui, je pouvais nid chaque fonction comme un rappel de sa fonction précédente. Mais cela deviendrait probablement lourd, une fois que vous considérez tous les différents cas d'utilisation.

est ici une approche J'envisage:

 
    1) Allow each function an optional callback parameter. If it's present, 
     call it at the very end of the function. 

    2) During a UI refresh, create an array, and stack any functions to be 
     called within this array. 

    3) Once this "script" is completed, iterate through the array, calling 
     each function in the order it was added, using the next function 
     as the previous function's callback. 

J'imagine que cela garantirait que toutes les fonctions sont appelées dans l'ordre.

Une autre approche est d'attacher des écouteurs d'événements à l'aide

$(document).bind("listener.name", fnCallback); 

Et puis appeler

$(document).trigger("listener.name"); 

Chaque fois que cet événement se produit.

Cependant, je suppose que ce serait un peu compliqué aussi, étant donné que différents événements pourraient avoir besoin d'appeler différents ensembles de fonctions en fonction du cas d'utilisation. Je pourrais toujours appeler

$(document).unbind("listener.name"); 

avant d'ajouter de nouveaux événements, mais encore une fois - je penche vers la création comme je l'ai suggéré dans la première approche une sorte de maître « script ».

Espérons que ce n'est pas trop vague - des commentaires? Une expérience avec des interfaces utilisateur complexes qui ont dû synchroniser divers événements?

Merci beaucoup,

Michael

Répondre

1

Votre approche # 1 est la meilleure façon, et la plus naturelle en utilisant jQuery. La plupart des fonctions qui agissent sur l'interface utilisateur et qui font quelque chose acceptent un paramètre de fonction de rappel, qui est appelé après l'exécution de la fonction. Si vous faites des choses qui ne sont pas implémentées dans jQuery en suivant le même modèle, votre code sera plus lisible.

La réponse de dominic est un bon exemple laconique:

function steps(){ 

    stepOne(stepTwo); 

} 

function stepOne(callback){ 

    var AsyncDone = function() { 
     //any Synchronus Things here 
     callback(); 
    } 
    someAsyncFunction(params, AsyncDone); 

} 
+0

Je pense que c'est un bon point qu'il suit la convention jQuery. Cependant, j'ai trouvé qu'il y a des moments où la mise en place d'un timeout de 1ms fera fonctionner les choses là où elles ne l'étaient pas auparavant. Cela n'a aucun sens pour moi (si les appels JS sont vraiment exécutés dans l'ordre - moins les appels asynchrones, bien sûr), mais c'est un bidouillage avec lequel je vais devoir vivre pour l'instant. Merci, tout le monde - tous les conseils très appréciés :) – marclar

+1

Je pensais que le code semblait familier! :) – DMCS

1

Essayez de passer dans la fonction à être rappelé comme un argument

function steps(){ 

    stepOne(stepTwo); 

} 

function stepOne(callback){ 

    var AsyncDone = function() { 
     //any Synchronus Things here 
     callback(); 
    } 
    someAsyncFunction(params, AsyncDone); 

} 
1

La dernière approche, l'utilisation des événements personnalisés, est la meilleure approche à mon humble avis.

Concevez divers composants et événements et laissez-les interagir les uns avec les autres.

E.g. Disons que vous avez un objet Calendar.

var calendar = function() 
{ 
    var pub = {}; 


    pub.highlightRow = function(row) {}; 

    pub.getRowByContent = function(content) { }; 

    pub.selectMonth = function() 
         { 
          //your code to actually select month. 

          //Once all the necessary DOM work is done, fire the 
          //monthSelected event (namespacing the event so as to avoid the clash with other events). 
          $(document).trigger('calendar:monthSelected'); 
         }; 

    return pub; 
}(); 

Maintenant, votre méthode de recherche d'artiste peut ressembler,

function searchArtist(artistName) 
{ 
    $(document).bind('calendar:monthSelected'), function() 
               { 
                calendar.highlightRow(calendar.getRowByContent(artistName)); 
               } 
               ); 

    calendar.selectMonth(getShowMonthByArtist(artistName)); 
}