AngularJS, promettent avec une fonction récursive

J'essaie d'utiliser la promesse AngularJS / puis avec une fonction récursive. Mais la fonction alors n'est pas appelée (aucune des erreurs, des succès, des notifications, des rappels sont appelés).

Voici mon code:

Fonction récursive

loadSection2 = function() { var apiURL = "http://..." var deferred = $q.defer(); $http({ method: "GET", url: apiURL }).success(function(result, status, headers, config) { console.log(result); loadCount++; if(loadCount < 10) { newSectionArray.push(result); loadSection2(); } else { loadCount = 0; deferred.resolve(); return deferred.promise; } }).error(function() { return deferred.reject(); }); deferred.notify(); return deferred.promise; }; 

puis

 loadSection2().then(function() { console.log("NEW SECTIONS LOADED, start adding to document"); addContent(); }, function() { console.log("ERROR CALLBACK"); }, function() { console.log("NOTIFY CALLBACK"); }).then(function() { loadScrollActive = false; }); 

Je pense que l'on doit alors au moins le premier rappel de notification. Mais il n'y a pas de rappel. Ne fonctionne-t-il pas avec la fonction récursive?

EDIT – 11/11/2015 Il existe une façon beaucoup plus propre si vous ne vous souciez pas d'aviser:

 loadSection2 = function (){ var apiURL = "http://..." return $http.get(apiURL) .then(function(response){ loadCount++; if (loadCount < 10) { newSectionArray.push(response.data); return loadSection2(); } loadCount = 0; }); }; 

Ancienne réponse disponible ici:

Vous pourriez toujours passer la promesse jusqu'au bout.

 loadSection2 = function(deferred) { if(!deferred){ deferred = $q.defer(); } var apiURL = "http://..." $http({ method: "GET", url: apiURL }).success(function(result, status, headers, config) { console.log(result); loadCount++; if(loadCount < 10) { newSectionArray.push(result); loadSection2(deferred); } else { loadCount = 0; deferred.resolve(); return deferred.promise; } }).error(function() { return deferred.reject(); }); deferred.notify(); return deferred.promise; }; 

Je voulais faire une solution qui ne passe pas la variable "différée" autour et même si je ne dirais pas que c'est une meilleure approche, cela fonctionne et j'ai appris cela ( jsfiddle ).

19 / Août / 14 – Mise à jour du code dans une version beaucoup plus courte en supprimant la création d'une autre promesse dans f1 (). J'espère qu'il est clair comment cela se rapporte à la question initiale. Si vous ne le faites pas dans un commentaire.

 f1().then(function() { console.log("done"); }); function f1(counter) { if (!counter) { counter = 0; } counter++; console.log(counter); return asyncFunc().then(function() { if (counter < 10) { return f1(counter); } else { return; } }); } function asyncFunc() { var deferred = $q.defer(); $timeout(function() { deferred.resolve(); }, 100); return deferred.promise; } 

Fauphi,

La récurrence est totalement viable, mais pas une approche particulièrement "prometteuse".

Étant donné que vous avez différé / promis disponibles, vous pouvez construire dynamiquement une chaîne .then() , qui offre une promesse d'un tableau peuplé.

 function loadSection2(arr) { return $http({ method: "GET", url: "http://..." }).then(function(result, status, headers, config) { console.log(result); arr.push(result); return arr;//make the array available to the next call to loadSection2(). }, function() { console.log("GET error"); return $q.defer().resolve(arr).promise;//allow the chain to continue, despite the error. //or I think $q's .then() allows the much simpler form ... //return arr; //allow the chain to continue, despite the error. }); }; var newSectionPromise = $q.defer().resolve([]).promise;//note that the deferred is resolved with an anonymous new array. //Now we build a .then() chain, ten long, ... for (var i=0; i<10; i++) { newSectionPromise = newSectionPromise.then(loadSection2); } // ... and do something with the populated array when the GETs have done their thing. newSectionPromise().then(function(arr) { console.log(arr.length + " new sections loaded, start adding to document"); addContent(arr); }, function() { console.log("ERROR CALLBACK"); }).then(function() { loadScrollActive = false; }); 

Non testé

Ce qui était newSectionArray est maintenant créé de manière anonyme et transmis la chaîne .then() , quelle que soit la réussite / l'échec des GET individuels, en émergeant comme arr dans le gestionnaire de réussite finale. Lorsqu'il est passé à addContent() . Cela évite le besoin de membre newSectionArray dans la portée extérieure.

Réorganisant légèrement, loadSection2 pourrait être rendu anonyme, réduisant encore le nombre de membres ajoutés à la portée externe.

La nécessité d'une notification explicite disparaît comme suit:

  • Il n'y a plus de maître différé à notifier
  • console.log(result); Dans le gestionnaire de réussite GET fournit toute la notification nécessaire.