Imbrication de promesses jQuery asynchrones

J’ai écrit un petit programme pour m’aider à comprendre comment faire des promesses asynchrones nestedes dans jQuery.

Je veux appeler deux tâches, en séquence. La première tâche a deux sous-tâches qui sont également appelées en séquence. C’est tout.

Bien que cela fonctionne, j’ai des doutes quant à savoir si c’était la meilleure façon d’utiliser les promesses. Devoir créer un nouveau différé pour chaque tâche donne l’impression que le code me sent. Par exemple, serait-il préférable de faire passer un seul object différé et de n’utiliser que cela? Merci!

doTasks().then(function(arg) { console.log(arg) }) function doTasks() { var d = $.Deferred(); task1().then(function(arg) { console.log(arg) task2().then(function(arg) { console.log(arg) d.resolve('all tasks are done') }) }) return d.promise(); } function task1() { var d = $.Deferred(); console.log("starting task1...") setTimeout(function() { task1A().then(function() { task1B().then(function() { d.resolve('task1 is done') }) }) }, 10); return d.promise(); } function task1A() { var d = $.Deferred(); console.log("starting task1A...") setTimeout(function() { console.log(" resolving task1A...") d.resolve(); }, 1000); return d.promise(); } function task1B() { var d = $.Deferred(); console.log("starting task1B...") setTimeout(function() { console.log(" resolving task1B...") d.resolve(); }, 1000); return d.promise(); } function task2() { var d = $.Deferred(); console.log("starting task2...") setTimeout(function() { d.resolve('task2 is done'); }, 1000); return d.promise() } 

Oui, c’est un peu nauséabond de créer beaucoup de reports inutiles.

Vous n’avez pas besoin de créer de différé pour vos opérations ajax. Si vous retournez une promesse à partir d’un gestionnaire .then() , elle est automatiquement chaînée à la promesse précédente (donc dans l’ordre) et tous les appels jquery ajax renvoient déjà des promesses. Vous n’avez donc pas besoin de créer vos propres promesses pour les opérations ajax. Et, vous pouvez enchaîner plutôt que nid afin de séquencer vos opérations.

En fait, créer des reports ou des promesses lorsque vous n’en avez pas besoin est appelé anti-modèle de promesse . Vous souhaitez utiliser et retourner les promesses déjà créées plutôt que d’en créer de nouvelles. Et, dans la mesure du possible, vous souhaitez enchaîner vos promesses plutôt que de faire votre nid.

Voici comment vous pouvez le faire dans un extrait exécutable sans créer un seul élément différé, sauf un emplacement, pour envelopper setTimeout() dans une promesse. Évidemment, vous pourriez utiliser beaucoup moins de code pour toutes vos tâches si vous leur créez une fonction réutilisable, mais je suppose que ce ne sont que des espaces réservés pour les opérations asynchrones réelles, donc je les laisse telles quelles fonction delay() partagée).

 doTasks().then(function(arg) { console.log("everything done"); }) function doTasks() { return task1().then(function(arg) { console.log(arg); return task2().then(function(arg) { console.log(arg) return arg; }) }) } // make promise version of setTimeout() in one central place // that can then be used elsewhere function delay(t) { return $.Deferred(function(def) { setTimeout(function() { def.resolve(); }, t); }).promise(); } function task1() { console.log("starting task1...") return delay(10).then(function() { return task1A(); }).then(function() { return task1B(); }); } function task1A() { console.log("starting task1A...") return delay(1000).then(function() { console.log(" resolving task1A...") return "done task1A"; }); } function task1B() { console.log("starting task1B...") return delay(1000).then(function() { console.log(" resolving task1B...") return "done task1B"; }); } function task2() { console.log("starting task2...") return delay(1000).then(function() { console.log(" task2 is done") return "done task2"; }); } 
  

Vous ne devriez pas imbriquer vos promesses. L’idée est que vous les enchaînez, en renvoyant une valeur dans le premier, then rappel, et que l’enchaînement d’un prochain, then que, dans son propre rappel, effectue l’étape suivante, … etc.

Lorsque vous utilisez une timer à plusieurs endroits pour résoudre une promesse, vous pouvez créer une fonction qui renverrait une telle promesse en plusieurs millisecondes.

Vous pouvez même créer une fonction qui produira quelque chose et renverra une promesse.

Cela vous permettra de tout enchaîner:

 doTasks().then(say.bind(null, 'all done')); function say(msg) { console.log(msg); return $.Deferred().resolve(msg).promise(); } function doTasks() { return task1().then(task2); } function delay(ms) { // one function for delaying as a promise var d = $.Deferred(); setTimeout(d.resolve.bind(null, ' delay completed'), ms); return say('starting delay of ' + ms + ' milliseconds...') .then(d.promise).then(say); } function task1() { return say('starting task1...').then(delay.bind(null, 10)) .then(task1A).then(task1B).then(say.bind(null, 'task1 done')); } function task1A() { return say('starting task1A...').then(delay.bind(null, 1000)) .then(say.bind(null, ' resolving task1A...')); } function task1B() { return say('starting task1B...').then(delay.bind(null, 1000)) .then(say.bind(null, ' resolving task1B...')); } function task2() { return say('starting task2...').then(delay.bind(null, 1000)) .then(say.bind(null, 'task2 done')); } 
 .as-console-wrapper { max-height: 100% !important; top: 0; }