2017-09-27 5 views
0

Aufgabe: Ich muss rekursiv durch ein JSON-Objekt gehen und bestimmte Änderungen an den Schlüsseln vornehmen. Ich werde Objekte mit unterschiedlichen Tiefen und unterschiedlicher Größe behandeln. Wenn die Funktion einen Schlüssel trifft, dessen Wert ein Objekt ist, wird es erneut für dieses Objekt aufgerufen.Node.js asynchrone rekursive Funktion mit Rückruf

Problem 1.: Dies als eine synchrone Funktion, bemerkte ich, dass große JSON-Objekte unvollständig zurückgegeben wurden. Unter Verwendung der die Asynchron-Bibliothek, löst async.forEach das Problem der langen Aufgaben der Handhabung und nur zurückkehren, wenn Sie fertig, aber ...

Problem 2.: Es scheint, dass die Asynchron-Funktion verliert Gleichzeitigkeit, wenn es rekursiv aufgerufen wird (?) (im Code-Snippet aufgezeigt).

Um diese Idee zu testen, entfernte ich den rekursiven Funktionsaufruf und es funktionierte (aber ohne Rekursion), und ich bekam einen Rückruf. Wenn ich den Funktionsaufruf hinzufüge, bekomme ich TypeError: results is not a function.

Dies führt mich zu der Annahme, dass async mit Callback und rekursive Funktionen nicht in Knoten mischen. Gibt es einen Weg, beides zu erreichen?

Mögliche Fix: Ich könnte eine separate Funktion laufe alle Schlüssel zu zählen und einen Zähler, wie meine Kontrolle in einer einfachen for Schleife verwenden, anstatt lassen forEach die Steuerung handhaben. Das scheint ein bisschen ineffizient, oder?

Hier ist der Code:

function fixJsonKeys(obj, results) { 
 

 
    async.forEach(Object.keys(obj), function(key, callback) { 
 

 
     if (typeof obj[key] == 'object') { 
 
       
 
      // do stuff to json key, then call the function 
 
      // on the nested object 
 
      
 
      fixJsonKeys(obj[key]); 
 

 
      callback(); // <-- how does this work with recursion?? 
 

 
     } 
 

 
     else { 
 
      
 
      // do stuff to json key 
 

 
      callback(); 
 
     } 
 

 
    }, function(err) { 
 

 
     if (err) return next(err); 
 
     
 
     // obj keys fixed, now return completed object 
 

 
     results(obj); 
 

 
    }); 
 
}

EDIT: hart in den Kommentaren zu formatieren, so:

@Laksh und @Suhail: Ich habe versucht, Ihre Anregungen und gleiche Ergebnisse . Wenn ich den Rückruf aus dem if Zustand entferne, sieht der async.forEach immer noch aus, um zu bestätigen, dass es die Tasten der obersten Ebene behandelt hat (denke ich).

Zum Beispiel sagen, dass ich 3 Top-Level-Schlüssel haben, und einer von ihnen hat ein verschachteltes Objekt:

[key1] (no callback, do recursion) 

    --[subKey1] 
    --[subKey2] 

[key2] (callback) 

[key3] (callback) 

async.forEach noch für einen Rückruf auf Aktion für key1 genommen suchen. Habe ich das richtig?

+0

Sie konnten nur den Callback im Basisfall der Rekursion –

+0

Einfach den 'Callback' nach dem rekursiven Aufruf im' if' Block entfernen –

+0

@Queenqueg, wie sieht die Eingabe für 'fixJsonKeys' aus?Und was ist der erwartete Output? – naomik

Antwort

0

Da Sie hier rekursive Funktionen verwenden, müssen Sie callback() nicht innerhalb der if-Bedingung aufrufen.

Das ist, weil Ihr rekursiver Aufruf zu dem vorhandenen callback() zurückkehrt, wenn einmal der gesamte rekursive Stapel für das bestimmte obj[key] beendet wurde.

Rekursive Funktion gibt nur zurück, wenn die Basisbedingung wahr ist, in Ihrem Fall wenn die Bedingung fehlschlägt, wird sie automatisch callback() von else block aufrufen.

Verwandte Themen