2017-05-06 4 views
1

Ich habe einen einfachen Baum mit IDs, die Schlüssel zu einer Mongo-Sammlung sind. Ich verwende eine Knotenbibliothek namens treewalker. Während ich jeden Knoten des Baumes durchlaufe, versuche ich, den Namen nachzuschlagen (mit Mungo) und ihn einfach an den aktuellen Knoten anzuhängen. Wenn ich keinen Rückruf mache, um den Knotennamen zu suchen, und nur einen festen Wert verwende, bekomme ich den Wert, den ich erwarte. Lassen Sie mich in Code veranschaulichen:Ausführen einer Funktion, nachdem ein Baumspaziergang mit Rückrufen abgeschlossen wurde

Hier ist mein Baum:

{ 
    "categoryTree": [ 
    { 
     "categoryId": "1", 
     "children": [ 
     { 
      "categoryId": "2", 
      "children": [ 
      { 
       "categoryId": "3", 
       "children": [] 
      }, 
      { 
       "categoryId": "4", 
       "children": [] 
      } 
      ] 
     }, 
     { 
      "categoryId": "5", 
      "children": [] 
     }, 
     { 
      "categoryId": "6", 
      "children": [] 
     } 
     ] 
    }, 
    { 
     "categoryId": "7", 
     "children": [ 
     { 
      "categoryId": "8", 
      "children": [] 
     } 
     ] 
    } 
    ] 
} 

Hier ist der Code, der tut, was ich will:

catTree.categoryTree.forEach(function(node){ 
    var counter = 0; 
    tree.walkTree(node, 'children', function(obj){ 
     obj.name = counter++; 
    }); 
}); 
//This tree has the names (as the counter above) in it as I expect 
console.log(JSON.stringify(catTree)); 

aber sobald ich in einem Mungo Rückruf werfen Holen Sie sich den Kategorienamen, der Kategorienbaum, der gedruckt wird, hat nicht mehr die Namen.

Ich weiß, dass dies ein Problem des Timings ist, aber ich kann nicht herausfinden, wie man es löst. Ich habe mehrere SO-Artikel like this one gesehen, die Callbacks nachverfolgen und nur fortsetzen, nachdem sie alle aufgerufen wurden. Ich kann nicht herausfinden, wie man dieses Muster auf meinen Fall anwendet, weil ich einen Baum spazieren gehe und nicht nur eine flache Liste wiederhole. Ich beginne zu denken, dass mein Problem möglicherweise, dass ich die Treewalker-Bibliothek verwende, vs nur meinen eigenen Algorithmus mit Callbacks schreiben, nachdem jeder Knoten besucht wird.

Ich schätze Ihre Hilfe wirklich!

+0

siehe async.js – Alex

Antwort

2

Ihre Datenbankaufrufe sind asynchron. Das bedeutet, dass sie irgendwann in der Zukunft abgeschlossen werden, lange nachdem die .forEach() Iteration abgeschlossen ist. Wenn Ihre Datenbank auf einmal auf mich einen ganzen Baum von Abfragen geworfen verarbeiten kann (Lauf all diese Abfragen im wesentlichen parallel), dann kann man etwas so einfache wie dies tut:

let cntr = 0; 
catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     ++cntr; 
     Cat.findById(obj.categoryId, {_id:0,name:1}).exec(function(err, value){ 
      --cntr; 
      if (!err) { 
       obj.name = value.name; 
      } 
      // see if all requests are done 
      if (cntr === 0) { 
       console.log(JSON.stringify(catTree)); 
      } 
     }); 
    }); 
}); 

Immer Sie versuchen zu koordinieren mehr als eine asynchrone Operation, macht es in der Regel Sinn, Versprechungen zu verwenden (da genau das ist, wofür sie gebaut wurden), und Mungo hat Versprechen für Abfragen eingebaut. Hier sammeln Sie ein Versprechen von jeder Abfrage in ein Array und dann Promise.all(), um Ihnen zu sagen, wenn sie alle fertig sind.

+0

Das ist genial! Danke für die Antwort und die versprochene Erklärung. Wenn ich dir ein Bier kaufen könnte, würde ich es tun. – tobyb

Verwandte Themen