Modèle de programmation jQuery asynchrone?

J’ai hérité d’une application qui parsing une page à la recherche d’atsortingbuts de données et modifie le dom, en ajoutant des gestionnaires, etc. en conséquence.

On m’a demandé d’implémenter un balisage dynamic permettant d’envoyer un appel ajax pour obtenir des données JSON, puis d’utiliser Handlebars pour afficher le nouveau code HTML en fonction des données renvoyées.

Je dois dire à l’application externe principale d’attendre que tous les appels JSON aient été résolus avant de rechercher des atsortingbuts de données.

Quel type de motif devrais-je mettre en place pour faire cela?

Toute aide serait très appréciée.

Merci Scott

Mettre à jour

outer.js – parsing les DOM à la recherche d’activités.

inner.js – émet 0 à 9 appels ajax (selon la page sur laquelle je suis). Chacun de ces appels ajax a une fonction .then () qui appelle les fonctions Handlebars pour écrire des balises.

Si je venais de recevoir un seul appel ajax, je pourrais renvoyer inner.js à outer.js en différé. Ensuite, dans la fonction .then () de cette ajax, j’appellerais simplement inner.js.resolve ().

Mais si je faisais cela pour chacun des 9 possibles inner.js se résoudrait après la première exécution, mais avant la fin de la deuxième.

Comment définir de manière dynamic le nombre de fichiers différés utilisés par outer.js pour attendre qu’ils soient TOUS résolus?

Il ne semble pas possible de lier tardivement un tableau comme ceci:

au sumt de inner.js:

var application = jQuery.Deferred(); var arrayOfAsync = []; application.done(arrayOfAsync); 

Ensuite, lorsque les sélecteurs jQuery sont trouvés sur une page, je pourrais faire un

 arrayOfAsync.push(localPromise); 

Mais cela n’a pas semblé fonctionner… devrait-il? Cela supposerait que le Deferred () (Deferred ()) tient vraiment à un tableau normal, ce qui pourrait ne pas être le cas …

Vous devriez utiliser des promesses dans cette situation.

Disons que vous avez votre modèle de guidon :

  

qui devrait être rempli avec une série de messages récupérés à partir d’un web api / web service.

Vous allez comstackr le modèle avant de l’utiliser:

 var myTemplate = Handlebars.comstack($("#PostsTempl").html()); 

Nous avons maintenant besoin d’une fonction qui appellera l’API Web / le service Web et obtiendra des données:

 function fetchData() { var deferred = $.Deferred(); $.ajax({ type: 'GET', dataType: 'json', url: 'my/api/posts/1/20', data: {}, success: function (jsonData) { if (jsonData) { deferred.resolve(jsonData); } else { deferred.reject(''); } }, error: function (req, status, error) { var errorMessage = (error.message) ? error.message : error; deferred.reject(errorMessage); } }); return deferred.promise(); } 

Nous allons utiliser $.ajax pour obtenir les données. Nous avons défini une promesse ici:

 var deferred = $.Deferred(); 

qui sera résolu lorsque nous récupérerons les données:

 success: function (jsonData) { if (jsonData) { deferred.resolve(jsonData); } else { deferred.reject(''); } }, 

Ou finalement, rejeté, s’il n’y a pas de données.

return deferred.promise(); retournera notre promesse.

Nous pouvons maintenant appeler la fonction qui résout la promesse et renvoie certaines données:

  fetchData() .then(function(data){ // console.log(data); var posts = {posts: data}; $("#posts").append(myTemplate(posts)); return true; }) .then(function(result){ goLookForDataAtsortingbutes(); }) .fail(function (reason) { if (reason !== '') { alert('Something went wrong:' + reason); } }); 

Lorsque nous récupérons les données, nous ajoutons les éléments à notre modèle:

 .then(function(data){ // console.log(data); var posts = {posts: data}; $("#posts").append(myTemplate(posts)); return true; }) 

Lorsque tout est terminé, nous appelons une autre fonction dans l’autre twig .then() :

  .then(function(result){ goLookForDataAtsortingbutes(); }) 

Les promesses peuvent être chaînées. le deuxième .then() est appelé après l’exécution du premier.

C’est le dernier bit dont vous avez besoin:

 function goLookForDataAtsortingbutes() { $('#posts li.item-handlebars').each(function (index, item) { $(item).addClass('big-font'); }); } 

Ce violon pourrait vous aider.

Dans cet exemple, j’parsing les publications et ajoute une classe lorsque handbards a rendu les éléments.

METTRE À JOUR:

Puisque vous appelez un service Web / API Web, vous pouvez exécuter les promesses en parallèle, attendre que toutes les demandes ajax soient terminées et exécuter votre dernière méthode.

Par souci de simplicité, je vais créer une fausse promesse (qui devrait être votre demande ajax):

 function buildPromise(id) { var deferred = $.Deferred(); setTimeout(function(){ var data = {id: id, name: 'name: ' + id}; deferred.resolve(data); }, 1000); return deferred.promise(); } 

et je vais créer un tableau de, disons, 10 promesses:

 var promises = []; for (var p = 0; p < 10; p++) { promises.push(buildPromise(p)); } 

Maintenant, je pourrai exécuter toutes ces promesses en parallèle:

 $.when.apply($, promises) .then(function () { for(var i = 0; i < arguments.length; i++) { $('#content').append('

' + arguments[i].name + '

'); } }).then(function(results) { return finalPromise(); }) .then(function(result){ alert('success: ' + result.success); alert('Finished'); });

$.when.apply($, promises) résout toutes les promesses ensemble, en parallèle, et revient lorsque nous obtenons tous les résultats.
Les résultats peuvent être trouvés dans des arguments et peuvent être lus à l'aide de l'index des arguments[x] du tableau arguments[x] .

Lorsque toutes les requêtes ajax ont été exécutées, nous allons appeler finalPromise :

 function finalPromise() { var deferred = $.Deferred(); setTimeout(function(){ var data = { success: true }; deferred.resolve(data); }, 1000); return deferred.promise(); } 

finalPromise pourrait être une fonction régulière, sans promesses non plus.

Voici à quoi ça ressemble.

Bien sûr, maintenant, vous devez l'adapter à votre situation.