Je recherche une solution élégante et efficace à mon problème:
J'ai cette webapp avec de nombreux composants; p>
Un composant principal comprend de nombreux ajouts qui vont se développer / évoluer avec le temps.
Ce composant principal a une fonction dans laquelle avant de faire ce qu'il est censé faire, il déclenche un événement Beforedo afin que les addons puissent écouter. P>
//app var $doc = $(document.body); //component $doc.on({ wait: function (e) { ++$doc.component.handleinprogress; }, addonready: function () { --$doc.component.handleinprogress; if ($doc.component.handleinprogress==0) $doc.trigger('readyfordo'); }, readyfordo: function () { //do stuff after event has been handled by the addons } }); $doc.component = { handleinprogress: 0, dostg: function () { $doc.component.handleinprogress = 0; $doc.trigger('beforedo'); } }; //in component addon files $doc.on('beforedo', function (e) { $doc.trigger('wait'); //do addon stuff $doc.trigger("addonready"); }
4 Réponses :
Pour attendre que tous les gestionnaires finissent avant d'exécuter du code, vous devez utiliser l'API En outre, JQuery's Votre code final devrait ressembler à quelque chose comme ceci: p> Si besoin est, quand vous appelez < Code> Callback () Code> Vous pouvez même passer à tout résultat que vous devrez peut-être passer comme un argument. En conséquence, modifiez la signature de fonction dans votre Développer sur le commentaire Si vous avez laissé ci-dessous, vous pouvez avoir une fonction de chargeur courant si vous aimez: p> voir: p> REFERRED CODE> DE JQRERY. Vous pouvez faire quelque chose comme ceci:
déclencheur < / code>
vous permet de passer des paramètres supplémentaires. Passez une fonction qui sera la fonction de rappel. P> .Trigger () code> appelez aussi. P>
Ouais mais alors où est la modularité? Je pense que c'est son problème, il a plusieurs addons avec des fermetures / contextes séparés et ne veut pas que le module principal dépend de les addons, mais de l'inverse.
Dans mon exemple ci-dessus, le $. Quand () code> n'a pas besoin d'avoir les appels Ajax. Il peut plutôt être à une fonction de chargeuse commune qui renvoie le
$. Ajax code> Promise en faisant la fabrication
$. Quand (chargez ("Fichier1"), chargez ("Fichier2")) CODE>
Yup, c'est bien. De cette façon, il peut retourner une promesse, non seulement $. Ajax code>. Je déteste toujours en utilisant une promesse où il n'y a pas d'appels asynchrones à partir de ...
va tester $ doc.trigger ('beforedo', fonction () {... code> pour comprendre comment cela fonctionne; NB: effectivement les addons n'impliquent pas nécessairement de chargement de données externes, pourraient être n'importe quoi (calculs, Regex Remplacer, DOM Access et Modifier) qui doivent être complètes avant que le maintien ne se poursuive avec son travail
S'il vous plaît voir mon édition & Apo à nouveau pour faire les choses l'autre sens
J'ai compris le rappel de la gâchette grâce à cela, je ne savais pas, mais cela ne correspond pas totalement à mon objectif; Je pense que je vais aller pour un mélange de votre solution de solution et @legec afin de donner à la prime? bien (pensant que je tape) depuis que Legec a moins de points et a fait une réponse plus longue et plus détaillée, désolé devait choisir
Consultez mon fidou ici . Votre idée de compter les demandes finies est bonne, c'est juste une question de code structurant.
Sachant que vous avez besoin de "modules / addons" découplés, c'est la façon dont j'irais: Utilisation de cette méthode, les addons peuvent avoir quelque chose en eux, il suffit de notifier "Main" quand Ils finissent ce qu'ils ont besoin de faire. P> Si j'étais vous, j'irais encore plus loin et que j'extraîtrais tout le code "gestionnaires" dans "Main" dans une classe distincte instanciée en tant que propriété publique dans "Main" avec AfterDoSTG code> en tant que paramètre. De cette façon, vous ne polut pas de code d'application avec méta truc comme celui-ci. P> p>
Ce n'est pas à moitié mauvais, je suggérerais un léger changement cependant: dans ce cas, les add-ons doivent savoir sur le principal code>. Pour supprimer cette limitation, vous pouvez utiliser un événement code> Beforedodone code>. Vous déclenchez ceci dans les add-ons, quand ils sont terminés. Vous ajoutez un auditeur à cet événement dans le
principal code> et vous décrémentez le compteur dans cet écouteur (et vous appelez le rappel code> code> de cet auditeur bien sûr). Qu'en penses-tu?
Mon code initial a utilisé cela, mais alors j'ai décidé que c'est un peu trop pour un POC. Mais oui, si vous avez besoin de plus de découplage, c'est la voie à suivre: jsfiddle.net/cvqdx/4
En réalité et je m'excuse de ne pas mettre à jour la question avant de mettre la prime, mais j'ai choisi d'aller pas longtemps après la question (et n'abandonnez pas de réponse à cette époque) avec quelque chose de très similaire @balintbako Solution; testera toutes les réponses données et voir laquelle que je préfère (en termes de performance - pour l'utilisateur et le codeur -> c.-à-d. Élégance "directe" et code)
S'il vous plaît voir mon édition & Apo à nouveau pour faire les choses l'autre sens
La solution que vous utilisez ne fonctionne pas correctement. Si vous avez 2 addons, le 1er reçoit l'événement et registre 'Wait', puis le même appelle Readyfordo. Que se passe-t-il avec le 2e? Il n'aura pas la chance d'intro.
Chacun de vos addons doit s'ajouter à une matrice globale et lorsque vous jetez votre événement, vous devez gérer le cas lorsqu'il n'y a rien dans le tableau, sinon vous utilisez le même code. Dans votre solution sans utiliser le guichet de la poignéeProgresse, utilisez plutôt la longueur de la matrice. P>
Vous pouvez également être intéressé par le modèle de promesse (voir objet différé dans JQuery Doc) qui rendent l'attente de manière asynchrone à un "événement "Une brise. p>
http://api.jquerery.com/category / objet différé / p>
http: //api.jQuery. com / repored.Promise / p> appeler: p> aussi simple que cela. P > p>
non, il fonctionne, tous les addons gèrent l'événement non seulement le premier ou le dernier (lorsqu'ils sont inscrits de toute évidence) et que chacun déclenche une attente manipulée par le composant Père incrémentant le compteur et car il y a toujours au moins un addon qui est faire quelque chose (ce qui me permet de ne pas ajouter de gestionnaire aux addons qui n'en ont pas besoin d'un - si je ajoute une manutention inutile, assurez-vous que AddonReady est déclenché au moins une fois, j'ai besoin d'un ensemble (1) avant de déclencher l'ajout Pour vous assurer que toute attente est déclenchée avant qu'un addonready est déclenché.
Pouvez-vous développer à l'aide d'un tableau (efficacement et asynchrone)?
Le tableau fait simplement référence à tous les objets des plugins (ils doivent être des objets). Chaque objet a des méthodes de plugin communes que votre «événement» peut appeler au lieu d'utiliser des événements DOM. La méthode init renvoie une promesse et dans la méthode "événement" que vous attendez de manière asynchrone pour que toutes les promesses soient "faites". Aussi simple que cela. Voir mon lien vers différé / promesses.
ok cela pourrait ressembler au début d'une amélioration de mon code et franchement suffisamment pour accepter la réponse, mais franchement pas assez pour la Bounty et mes points gagnés (désolé) car il ne correspond pas aux spécifications qui ne correspondent pas aux spécifications: ce n'est pas un Événement instantané -> La plupart addon n'ont pas de travail à faire sur cet événement composant (seulement certains ont, et parfois non) - s'il vous plaît pour la prime adapter cette idée à ma structure et spécifications de code
Softlion a souligné plusieurs points, avec lesquels je suis d'accord.
Problèmes potentiels: forte > p> Un problème peut survenir avec votre implémentation actuelle, si l'un de vos addons appelle Dans ce cas, en fonction de l'ordre de résolution de vos rappels, vous pouvez déclencher accidentellement votre événement Votre code s'appuie également sur l'hypothèse que tous vos addons seront toujours exécutés Exactement un Tant que tout votre code est en interne, vous pouvez en avoir le contrôle, mais cela semble-t-il cassant . P> Les différés / promesses de JQuery: strong> p> Un modèle générique consiste à utiliser les promesses de JQuery. Tous les appels asynchrones de JQuery's sont maintenant enveloppés dans des promesses et la bibliothèque propose une API qui permettra de manipuler les personnes de manière assez élégante - et il a probablement été testé dans plus de cas de coin que votre propre code. P> Voici mes 2 cents: p> au lieu d'utiliser votre à peu près parlant: Dans vos addons, vous remplacez Vous pouvez ensuite laisser le < CODE> $. Quand () CODE> La fonction prenne soin de tout ensemble et attendez ce qui devrait être attendu. p> mise à jour em>: effectivement, si stockés dans un tableau, vous devez appeler $ doc.trigger ("addonready"); code> synchrone em>: < / p>
ReadyFordo CODE> après que le premier addon ait déclenché son
AddonReady CODE> fonction, et avant que la seconde ait eu une modification de la gâchette
attendre code>. p>
.trigger ('Addonready') code> pour chaque
.trigger ('wait') code>. Je ne sais pas comment votre code ressemble, ni combien d'addons que vous avez, mais en vous assurant que c'est le cas pour chaque chemin d'exécution possible est un obstacle à un obstacle (par exemple: avez-vous testé le
2 ^ n code > cas de défaillance si vous avez
n code> ajax appels?) p>
Beforedo code>,
attendre code>,
addonready Code> Événements, vous avez vos plugins enregistrez une fonction dans un
inadqueue code> connu par votre composant - Notez que vous pouvez choisir pas em> pour enregistrer le rappel si votre addon n'a pas besoin un. P>
$ doc.on ('Beforedo', fonction () {...}) code> avec
$ doc. composant.initqueue.push (fonction () {...}) code>, et si vous avez besoin d'attendre quelque chose, vous retournez une promesse autour de ce quelque chose. P>
$. à poule code> attend les promesses comme des arguments distincts p>
$. Quand.Appliquez ($, tableau) code> pour adapter la signature de la fonction . P>
$. Quand (tableau) code> considérera que son argument (le tableau) n'est pas une promesse, et résolve immédiatement. P>
J'utilise un Settimeout pour déclencher AddonReady si STG mais pas Ajax, pas vraiment un problème, pas si élégant, je suis d'accord pourquoi je cherche une autre façon. Il manque quelque chose dans votre code, c'est le cas où le tableau de la fonction est vide (à moins qu'un tableau vide n'est considéré comme résolu par quand () code> ??)
@mikakun: oui, quand () code> traitera des non-promesses comme "résolues" et déclenchera également
.commlete code> si vous donnez une liste de paramètres vide. Je n'avais pas testé mon code,
$. Quand code> attend effectivement des arguments distincts (pas un tableau). Vous devrez utiliser
$. Quand.Appliquez ($, tableau) code> pour alimenter un tableau (moins élégant).
Bounty à vous pour une belle explication sur l'utilisation de la promesse et accepter à Xbonez pour m'apprendre le rappel de la gâchette qui sera utile aussi, je pense