2015-12-18 6 views
8

Entschuldigen Sie, wenn ich eine bereits sehr gestellte Frage wiederhole, aber alles, was ich bisher gesehen habe, scheint mir nicht rekursiv zu sein oder nicht zu dem, was wir tun, und Das Thema Versprechen und Zurückgestelltes scheint für mich sehr komplex zu sein.Wie man ein rekursives JQuery-Versprechen richtig codiert

Ich habe einen "Themenbaum", der asynchron erstellt wird, wenn der Benutzer Knoten erweitert. Dieses Thema wird mithilfe eines API-Endpunkts erstellt, der die untergeordneten Elemente eines Knotens beim Klicken auf die Schaltfläche (+) auf dem Zweig des Zweigknotens zurückgibt.

Wenn der Benutzer auf die Schaltfläche klickt, ich versuche rekursiv Thema Baumelemente zu laden ein Verfahren, das wie folgt aussieht:

function getAssociatedTopics(){ 
    $.get('/topics/curriculum-associations', {guids: [...]}) 
    .then(function(data){ 

     //Process the topic information here 
     var topicId = /* some processing */; 

     //Get ancestors of each topic returned 
     $.get('/topics/getAncestors', {of: topicId}) 
     .then(function(data){ 

      //Process the topic information here 
      var topicId = /* some processing */; 

      //Get ancestors of each topic returned 
      //Rinse repeat as long as we find children of each topic found 


     }); 

    }).then(function(){ 

     //Expand the nodes 
     //Select the nodes 

    }); 
} 

Also das ist, was es aussehen sollte, aber ich bin ganz verloren das Lesen Dokumentation, um sicherzustellen, dass meine Sachen in der richtigen Reihenfolge ausgeführt werden ... Das große Problem, das wir gerade mit dieser Struktur haben, ist, dass meine Knoten alle gleichzeitig laden und dann die ausgewählten Knoten löschen, Knoten jederzeit öffnen und schließen und die Auswahl endet super chaotisch.

Ich möchte keine eingehende Erklärung der Versprechen, noch möchte ich eine vollständige Lösung, sondern eine allgemeine Idee, wie dies zu erreichen ist.

+0

Sie möchten den Knoten Teilbaum erweitern? Oder nur die ersten Kinder? – MinusFour

+0

Sie sagen "wenn der Benutzer auf die Schaltfläche klickt", ist diese Schaltfläche die Schaltfläche "(+)" auf dem Zweig des Themenbaums oder eine andere Schaltfläche? Weil Sie * sagen * haben Sie "einen API-Endpunkt, der die Kinder eines Knotens zurückgibt", aber Sie haben nichts gezeigt, was dies noch deutlich macht (es sei denn, das ist was "/ topics/curriculum-associations" tut). –

+2

Außerdem sagt der Code * Holen Sie die Vorfahren jedes Themas zurückgegeben *, was zu der Annahme führt, dass es eine Schleife gibt, die wir nicht sehen. Eine Schleife, die sehr gut die Korrektheit der Antwort bestimmen könnte ... –

Antwort

1

Zunächst einmal, die Komplexität des Abrufs, was Sie brauchen, sollte auf dem Server und nicht der Client behandelt werden. Hunderte von HTTP-Anforderungen vom Client zu erstellen ist ein Performance-Desaster, das darauf wartet, ausgeführt zu werden.

Nun, wie Sie es tun würde, zwei wichtige Fakten:

  • Promises Arbeit von den Rückgabewert verwendet wird. $.get gibt ein Versprechen für den Wert - das ist, warum Sie then davon ab, aber Sie können es auch nach außen zurückgeben.
  • Wenn Sie ein Versprechen von einem then Handler zurückgeben, wird das Versprechen aus dem then selbst warten auf das innere Versprechen, zuerst aufzulösen.

Hier ist ein Beispiel veranschaulicht, die zwei Punkte:

$.get("/api").then(function(data) { 
    return $.get("/api2/" + data.id); 
}).then(function(data2) { 
    // because of point #1, we get the data of the inner call here. 
}); 

Nun, für Ihre eigentliche Problem:

function getAssociatedTopics(guids) { 
    // note the `return` here so it can be chained from outside 
    return $.get('/topics/curriculum-associations', {guids: guids}) 
    .then(function(data){ 
     var topicId = someProcessing(data); 
     // note we return here. I assume this get returns guids. 
     return $.get('/topics/getAncestors', {of: topicId}) 
    }).then(function (guids) { // this anonymous function can be inlined 
     if(guids.length === 0) return; // stop condition 
     return getAssociatedTopics(guids); // note the recursive call, remember point #2. 
    }); 
} 
getAssociatedTopics(initial).then(function(){ 
    // all done 
}); 

Wenn Sie die Ergebnisse aller Anrufe benötigen, können Sie es ketten aus, oder Sie können auf ein Closure-Variablen-Array innerhalb des vor dem letzten schieben und im all-done-Handler darauf zugreifen.