2016-07-19 9 views
-2

Ich habe einen Code geschrieben, um Swagger 1 Dokumentation zu Swagger 2 zu konvertieren. Ich verweisen die Konvertierungsmethode auf mehrere Ressourcen in einem Array. was ich finde ist, dass es nicht korrekt ausgeführt wird und sehe es im Debugger den ganzen Weg bis zum Ende meines Arrays springen (die Größe 34 ist). Wie stelle ich sicher, dass mein Code korrekt durchläuft?Korrigieren Sie für die Implementierung der Schleife

for(var i = 0; i < resourcesArray.length; i++) { 
    Converter.convert({ 
     from: 'swagger_1', 
     to: 'swagger_2', 
     source: 'http://example/' + resourcesArray[i] 
    }, function (err, converted) { 
     console.log(resourcesArray[i]); 
     // [Optional] Fill missing fields with dummy values 
     converted.fillMissing(); 

     // [Optional] Validate converted spec 
     var fileName = resourcesArray[i] + '.json'; 
     fs.writeFileSync(fileName, converted.stringify()); 
    }) 
} 
+0

das ist ... was for-Schleifen tun ... es iteriert über das ganze Array, was ausführt, was drin ist. Die Callback (s) passieren einige Zeit später und es ist nicht garantiert, dass sie in der richtigen Reihenfolge sind. –

Antwort

1

Sie sind den Scoping-Regeln für JavaScript zum Opfer gefallen. Versuchen Sie folgendes:

resourcesArray.forEach(function (resource) { 
    Converter.convert({ 
     from: 'swagger_1', 
     to: 'swagger_2', 
     source: 'http://example/' + resource 
    }, function (err, converted) { 
     console.log(resource); 
     // [Optional] Fill missing fields with dummy values 
     converted.fillMissing(); 

     // [Optional] Validate converted spec 
     var fileName = resource + '.json'; 
     fs.writeFileSync(fileName, converted.stringify()); 
    }); 
}); 

Das Problem war, dass der asynchrone Rückruf durch die Zeit function (err, converted) { ... } auftritt, i zu resourcesArray.length gleich ist, weil die Iteration bereits abgeschlossen ist. So funktioniert JavaScript var deklarierte Variablen. Durch die Verwendung einer forEach-Schleife wird sichergestellt, dass der Bereich immer die resource enthält, die Sie für diesen Vorgang erwarten.

Alternativ, wenn ES6 in Ordnung ist, dann könnte man var-let ändern und das würde löst auch das Problem, weil let -declared Variablen lexikalischen Scoping verwenden, was bedeutet, dass der für Loop-Block wird immer den erwarteten Wert von i enthält auch wenn es in einem asynchronen Callback verwendet wird.

+0

Das macht alles klar für mich. Vielen Dank! – user3221287

-2

Dies kann passieren, weil es einen asynchronen Aufruf in Ihrer for Schleife gibt. Sie müssen den Wert i für jede Iteration einfrieren. Sie können dazu closure() verwenden. Wenn Sie den Überblick behalten möchten, wenn alle Iterationen abgeschlossen sind, können Sie einen Zähler beibehalten: var counter = resourcesArray.length; für (var i = 0; i < resourcesArray.length; i ++) { var resources = resourcesArray [i];

(function(resources, i){ 
    Converter.convert({ 
     from: 'swagger_1', 
     to: 'swagger_2', 
     source: 'http://example/' + resources 
    }, function (err, converted) { 
     console.log(resources); 
     // [Optional] Fill missing fields with dummy values 
     converted.fillMissing(); 

     // [Optional] Validate converted spec 
     var fileName = resources + '.json'; 
     fs.writeFileSync(fileName, converted.stringify()); 

     counter--; 
     if(counter <= 0) 
     { 
      //next(); 
     } 
    }) 
    })(resources, i);  
}//for 
1

Sie richtig sind Looping, aber das Problem ist, dass kein JavaScript einen Verschluss für for Körper. Da Sie einen asynchronen Vorgang innerhalb der Schleife starten, hat sich der Wert i geändert, bis der asynchrone Vorgang abgeschlossen und Ihr Rückruf aufgerufen wurde.

So müssen Sie sofort eine Schließung innerhalb der for-Schleife erstellen, speichern Sie den gewünschten Wert innerhalb der Schließung, und rufen Sie dann die asynchrone Operation beim Definieren der Rückruf innerhalb der Schließung.

for(var i = 0; i < resourcesArray.length; i++) { 
    (function(i) { 
    // Do work here with the value i 
    })(i); 
} 
+0

Nur eine Randnotiz, wenn ES6 akzeptabel ist, 'für (let i = 0; i

Verwandte Themen