2017-12-24 3 views
0

Es tut mir leid, wenn ich etwas vermisse - ich lerne immer noch Node-Logik (vor allem asynchrone Jobs).Request und WriteStream Dateiname

Ich möchte eine Zip-Datei herunterladen, dann speichern und entpacken. Es sieht wie folgt aus:

request(URL) 
    .pipe(fs.createWriteStream(/path/to/filename)) 
    .on('close', function() { 
     // I want to unzip and I need access to filename 
    }); 

Nun ist die Sache, wenn ich eine filename Variable vorher festgelegt, da es in einer Schleife ist, durch die Zeit, die Datei heruntergeladen wird, filename wird der Wert der letzten Schleife Iteration haben.

Natürlich sehe ich, dass wir es tun können, indem wir eine Funktion definieren, die all dies tun würde, wie fecthAndUnzip(URL,path). Aber meine Frage ist eher designbezogen: Ist es der einzige Weg, wie wir es in Node schaffen können, oder gibt es einen besseren? Zum Beispiel, kann ich auf den Dateinamen im on('close') Ereignis zugreifen und wenn ja, sollte ich? Vielen Dank!

Antwort

1

Das Definieren einer separaten Funktion ist definitiv nicht die einzige und es gibt eine viel bessere.

Sie zeigen nicht den vollständigen Code an, aber ich nehme an, dass Sie aufgrund des Verhaltens var Ihre Variable definieren. Wie in var filename = 'something'. Wenn Sie dies tun, definieren Sie die Variable filename im globalen Bereich [function]. Dies bedeutet, dass es für jeden Teil der Funktion verfügbar ist, unabhängig davon, wo es definiert wurde. In Ihrem Fall, obwohl Sie die Variable in der Schleife definieren, ist sie in der gesamten Funktion begrenzt, so dass Sie bei jeder Iteration diese Variable tatsächlich überschreiben.

Es gibt eine gute Antwort über Stackoverflow Bereiche hier, wenn Sie mehr erfahren möchten, oder ob ich es gut genug, um nicht zu erklären war: https://stackoverflow.com/a/11444416/6359249

Die Lösung wäre eine Variable in dem aktuellen Block Bereich zu definieren. Wenn Sie eine neuere Version von node.js verwenden, die ES6 implementiert, können Sie let (oder const für konstante Variablen) verwenden. Im Gegensatz zu var wird dadurch eine Funktion im aktuellen Block definiert. Wenn Sie es in einer Schleife definieren, ist es nur für diesen Block zugänglich und wird nicht geändert. Zum Beispiel:

for (let i = 0; i < files.length; i++) { 
    let filename = files[i]; 
    // Do stuff 
} 

Hinweis let i = 0. Die gleichen Lösungskonzepte gelten für Schleifenvariablen.Es ist ein häufiges Problem für Leute, var i = 0 zu benutzen und verwirrt zu werden, wenn man eine asynchrone Funktion benutzt und das Entdecken i ist der letzte Wert von i.

Wenn Sie nicht ES6 verwenden, können Sie eine anonyme Funktion jede Schleife definieren:

for (var i = 0; i < files.length; i++) { 
    var filename = files[i]; 
    (function (file) { 
    // Do stuff 
    })(filename); 
} 

die die gleiche wie die Lösung ist, dass Sie außer Sie beschrieben erstellen und die Funktion im laufenden Betrieb ausgeführt werden. Wenn Sie ES6 aus irgendeinem Grund nicht verwenden, ist Ihre ursprüngliche Antwort zum Erstellen einer separaten Funktion wahrscheinlich die beste Lösung.

+0

Große, umfassende Antwort auch. Meine Frage war mehr designbezogen (obwohl ich immer noch neugierig auf meinen speziellen Anwendungsfall mit 'fs.createWriteStream()' bin, d. H. Wenn wir den Dateinamen in 'on ('close')' holen können). Ich verwende tatsächlich ES6, und genau deshalb hatte ich dieses Problem. Ich wusste, dass die Funktion funktionierte (so war ich in der Vergangenheit), aber ich lerne immer noch ES6 und ich glaube, dass es wichtig ist, diese Konzepte schnell zu integrieren. Danke und danke auch für den Link! – Johy

+1

Ich sehe was du jetzt meinst, die Antwort gibt es nicht. Die Veranstaltung ist ziemlich unabhängig, glaube ich und es wird erwartet, dass andere Informationen an anderer Stelle abgerufen werden. – Froast

+0

Macht vollkommen Sinn und ich lernte Best Practices, die ich auf dem Weg nicht kannte. Vielen Dank! – Johy

1

Sie wissen nicht, ob es Ihnen hilft, aber das Problem, das Sie für die Schleife beschreiben hat mehrere Lösungen: statt var

erste, verwenden lassen Sie die Variable zu binden, um es aktuellen Bereich ist:

for (let i = 0; i < 4; i++) { 
    setTimeout(function() { 
    console.log('test 2', i); 
    }, 2000); 
} 

Dies wird 0, 1, 2, 3 drucken, auch wenn die Schleife endet, bevor der erste Timeout-Callback aufgerufen wird.

Sie forEach statt for-Schleife verwenden können, wenn es ein Array ist

[0, 1, 2, 3].forEach(function(i) { 
    setTimeout(function() { 
    console.log('test 3', i); 
    }, 3000); 
}) 

Sie eine externe Funktion verwenden können:

for (var i = 0; i < 4; i++) { 
    setTimeout(function() { 
    logI(i); 
    }, 100); 
} 

function logI(i) { 
    console.log(i); 
} 

das einzige, was ist wichtig, dass Ihre Variable gebunden sein muss zu einem internen Bereich, um seinen Wert zu behalten, selbst wenn die Schleife endet, bevor Ihre asynchrone Funktion aufgerufen wird.

+0

Fantastisch, es beantwortet definitiv meine Frage. Die einzige Lösung, die ich hatte, war # 3 (die ich umgesetzt habe), aber ich suchte nach allgemeinen Praktiken für diesen Anwendungsfall. Ich bin froh, dass ich die beiden anderen gelernt habe, die ich sehr oft benutzen werde. Vielen Dank! – Johy

Verwandte Themen