• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Promise-Chain mit For-Loop verbinden ?

alphakanal

New member
Hi!

Hoffe alle hatten schöne und erholsame F(EIER)tage :)

Passend zum Wetter habe ich auch schon wieder eine Frage/Problem. Ich lade ein JSON mit mit einem Array aus Objekten. Jedes Objekt steht für eine Person. Und jedes Objekt hat ein Attribut "name" welches ich nutzen möchte um anschließend ein JSON mit Details zur jeweiligen Person zu laden. Den Inhalt der "Details-JSON" möchte ich dann in das zuvor geladene "Personen-JSON" in das Attribut "details" packen.

Code sieht folgendermaßen aus:
Code:
function fetchPersonen() {

  return $http.get('mein-pfad/json/personen.json')

    .then(fetchDetails)
    .then(fetchImages)
    .catch(fetchLabelsFailed);

  function fetchDetails(response) {
    var res = response.data; // Array mit den Personen
    return loadDetails(res); // lädt pro Person ein JSON-File mit Details
  }

  function fetchImages(response) {
    return loadImages(response); // wie Details nur mit Bilder
  }
}

function loadDetails(response) {

  var q = $q.defer();

  for (var i = 0; i <= response.length; i++) {
    if (i < response.length) {
      var details2load = 'mein-pfad/json/details/' + response[i].name + '.json';
      var details = $http.get(details2load);
      response[i].details = details;
    }
    else {
      q.resolve(response);
    }
  }

  return q.promise;
}

Doch so wie ich das mache klappt das nicht so recht - ausserdem wird hier im For-Loop alles quasi in einem Rutsch alles geladen ohne abzuwarten ob das vorherige JSON fertig geladen ist. Weiß hier evtl jemand nen kleinen Anstoß um den richtigen Weg zu finden?
 
Und das heißt was genau?

Das Problem liegt eigentlich nicht in dieser Schleife sondern was anschließend in fetchImages() passiert -> die holt Infos aus details und da sind die Detail-JSONs teilweise noch nicht fertig geladen. Das liegt wohl daran dass q.resolve() erfolgt sobald die for-Schleife durch ist und nicht wenn alle JSONs geladen sind.
 
Zuletzt bearbeitet:
Hmm..steh jetzt mal wieder aufm Schlauch.

Lade meine Detail-JSONs jetzt mit $q.all(), verarbeite es weiter und lass mir das Ergebnis via console Ausgeben -> hier ist es so wie es sein soll.

Jedoch bekomme ich eine Fehlermeldung mit der ich nichts anfangen kann:
Possibly unhandled rejection: {} angular.js

Screenshot der Fehlerdetails:
fehler.JPG

Jemand ne Idee was da falsch läuft?
 
Zuletzt bearbeitet:
Ich auch ned ;) Was ich halt seltsam finde ist:
Wenn ich die Details nicht aus separaten JSONs lade und einfüge sondern gleich in die "Personen-JSON" schreibe gibt es den Fehler nicht. Wobei das Ergebnis laut Konsole gleich ist ?!?


Irgendwie hab ich trotzdem das Gefühl das mein Code auch ned so 100% richtig ist:
Code:
function fetchPersonen() {

  return $http.get('mein-pfad/json/personen.json')

    .then(fetchDetails)
    .then(fetchImages)[COLOR="#FF0000"] // wann erhält fetchImages den return wert aus fetchDetails ??[/COLOR]
    .catch(fetchLabelsFailed);

 function fetchDetails(response) {
  var res = response.data; // Array mit den Personen
  var promises = [];
  for (var i = 0; i < res.length; i++) {
    var promise = $http.get('mein-pfad/json/' + res[i].cn + '.json');
    promises.push(promise);
  }

  $q.all(promises)
    .then(function (promises) {
      for (var i = 0; i < res.length; i++) {
      console.log('$q.all.then()', promises[i].data);
        res[i].details = promises[i].data;
      }

    });
  return res; [COLOR="#FF0000"]// wird das erst zurückgegeben wenn $q.all().then(...) erfolgt ist, nein oder??[/COLOR]
}

  function fetchImages(response) {
   ...
  }
}
 
Zuletzt bearbeitet:
wenn fetchDetails fertig ist.
Das ist komisch: Denn ich lasse in fetchImages via console.log was ausgeben - und das wird VOR dem console.log innerhalb $q.all() .then(...) ausgegeben. Oder hat das nichts zu sagen?

nein, es wird zurückgegeben, wenn .then() aufgerufen wurde. Du mußt die Promise weitergeben, nicht irgendwelche Variablen außerhalb der Promise.
Glaub hier liegt dann wohl auch der Fehler. Denn meine Absicht war es das Personen-Array ( = res ) in fetchDetails() mit den Details zu erweitern und das erweiterte Personen-Array an fetchImages() weiter zu geben.

Hmm...aber was muss ich dann hier jetzt dann weitergeben? Das Promises-Array ?

MeinVerwirrungsIndex++
 
Zuletzt bearbeitet:
Das Promise-Return-Schema ist eigentlich gar nicht so kompliziert, allerdings muss man sich konsequent dran halten ...

PHP:
var p = new Promise(...);

p.then(function (resolved_value_1) {
    // do something with resolved_value_1

    return value_or_promise;
}).then(function (resolved_value_2) {
    // do something with resolved_value_2

    return value_or_promise;
})
// usw.
 
Das ist komisch: Denn ich lasse in fetchImages via console.log was ausgeben - und das wird VOR dem console.log innerhalb $q.all() .then(...) ausgegeben.
q.all startet ja einen weiteren asynchronen zweig/bzw. wartet auf deren response.
fetchDetails wartet ja nicht auf dessen ende, sondern returnt gleich. darauf wird fetchImages ausgeführt. das then von q.all wartet dann noch auf das ende aller asynchronen requests
 
Code:
[COLOR="#FF0000"]return [/COLOR]$q.all(promises)
    .then(function (promises) {
      for (var i = 0; i < res.length; i++) {
      console.log('$q.all.then()', promises[i].data);
        res[i].details = promises[i].data;
[COLOR="#FF0000"]        return res[i];[/COLOR]
      }

    });
du musst das promise welches q.all zurückliefert zurückgeben. um in fetchImages das array mit den daten zu bekommen, müssen die einzelnen promises welche in q.all gebündelt werden auch daten zurückliefern.
q.all packt alle daten der einzelnen promises in ein array und übergibt dieses an das nächste callback in der chain

- - - Aktualisiert - - -

noch zum verständniss:
wie könnte ich fetchDetails() dazu bekommen erst zu returnen wenn q.all.then() ausgeführt wird?
fetchDetails "returnt" sofort, das callback fetchImages aber wird erst dann aufgerufen (then), wenn das promise resolved wird.

- - - Aktualisiert - - -

wobei ich gerade sehe, dass das auch falsch ist, das sind ja nicht die then-callbacks der einzelnen promisses, sondern vom q.all
Code:
[COLOR="#FF0000"]return [/COLOR]$q.all(promises)
    .then(function (promises) {
      for (var i = 0; i < res.length; i++) {
      console.log('$q.all.then()', promises[i].data);
        res[i].details = promises[i].data;
[COLOR="#FF0000"]        return res[i];[/COLOR]
      }

    });
damit musst du res zurückliefern

Code:
[COLOR="#FF0000"]return [/COLOR]$q.all(promises)
    .then(function (promises) {
      for (var i = 0; i < res.length; i++) {
      console.log('$q.all.then()', promises[i].data);
        res[i].details = promises[i].data;
      }
      [COLOR="#FF0000"]        return res;[/COLOR]
    });
 
wobei ich gerade sehe, dass das auch falsch ist, das sind ja nicht die then-callbacks der einzelnen promisses, sondern vom q.all
damit musst du res zurückliefern
Das hab ich sogar von selbst bemerkt ... YEAH Ich will Feuerwehrmann werden !!!

Vielen Dank nochmal - funktioniert perfekt und die Fehlermeldung ist weg :D

Da ich gerne "übersichtlicher" habe, noch eine formale Frage: Wenn ich q.all ().then() in eine Variable packe und diese dann als return Wert angebe:

Code:
var xyz = $q.all(promises)
    .then(function (promises) {
      for (var i = 0; i < res.length; i++) {
      console.log('$q.all.then()', promises[i].data);
        res[i].details = promises[i].data;
      }
              return res;
    });

return xyz;

Ergebnis ist das selbe. Wäre das eine persönlicher-Stil-Lösung oder gibt's hier ( bis auf den zusätzlichen Code ) Nach- oder Vorteile ?
 
Zurück
Oben