So verwenden Sie die Stream-API von Node.js nicht

    Im Internet ist wieder jemand nicht richtig - in dem gestrigen Knoten Weekly wurde ein Link zu dem Beitrag , in dem der Autor versucht , mit „analog“ Performance Stream - API in Node.js. zu messen und zu vergleichen Traurigkeit bewirkt, wie der Autor mit Streams arbeitet und welche Schlussfolgerungen er daraus zu ziehen versucht:


    ... das hat bei kleineren Dateien ganz gut funktioniert, aber als ich die größte Datei gefunden habe, ist derselbe Fehler aufgetreten. Obwohl Node.js die Ein- und Ausgaben gestreamt hat, wurde versucht, die gesamte Datei im Speicher zu halten, während die Vorgänge ausgeführt wurden

    Versuchen wir herauszufinden, was mit den Schlussfolgerungen und dem Code des Autors nicht stimmt.


    Aus meiner Sicht besteht das Problem darin, dass der Autor des Artikels nicht weiß, wie man Stream'ami verwendet, und dass es sich um ein Problem handelt, mit dem man sich ziemlich oft befasst. Dieses Phänomen hat meiner Meinung nach drei Gründe:


    1. Die komplexe Geschichte der Node.js Stream-API - die hier beschriebenen Schmerzen und Leiden
    2. Nicht die intuitivste API, wenn Sie versuchen, sie ohne Wrapper zu verwenden
    3. Ziemlich seltsame Dokumentation, die Streams als etwas sehr Komplexes und Geringes darstellt

    Alles in allem führt dies dazu, dass Entwickler häufig nicht wissen, wie und nicht die Stream-API verwenden möchten.


    Was ist mit dem Autorenkode falsch ?
    Wiederholen Sie die Aufgabe zunächst hier (das Original in englischer Sprache und einen Link zur Datei finden Sie im Beitrag):
    Es gibt eine bestimmte 2,5-GB-Datei mit folgenden Zeilen:


    C00084871|N|M3|P|201703099050762757|15|IND|COLLINS, DARREN ROBERT|SOUTHLAKE|TX|760928782|CELANESE|VPCHOP&TECH|02282017|153||PR2552193345215|1151824||P/R DEDUCTION ($76.92 BI-WEEKLY)|4030920171380058715

    Sie müssen es analysieren und die folgenden Informationen herausfinden:


    • Die Anzahl der Zeilen in der Datei
    • Namen in der 432. und 43243. Zeile (hier stellt sich die Frage, wie von 0 oder 1 zu zählen ist)
    • Der häufigste Name und wie oft er vorkommt
    • Die Anzahl der Raten pro Monat

    Was ist das Problem? - Der Autor sagt ehrlich, dass er die gesamte Datei in den Speicher lädt und aus diesem Grund „hängt“ der Knoten und der Autor gibt uns eine interessante Tatsache.


    Unterhaltsame Tatsache: Node.js kann nur bis zu 1,67 GB gleichzeitig speichern

    Der Autor zieht aus dieser Tatsache eine seltsame Schlussfolgerung, dass es die Streams sind, die die gesamte Datei in den Speicher laden, und er hat nicht den falschen Code geschrieben.
    Lassen Sie uns die These widerlegen: " Obwohl Node.js die Ein- und Ausgaben gestreamt hat, wird immer noch versucht, die gesamte Datei zu speichern ", indem Sie ein kleines Programm schreiben, das die Anzahl der Zeilen in einer Datei beliebiger Größe zählt:


    const { Writable } = require('stream')
    const fs = require('fs')
    const split = require('split')
    let counter = 0
    const linecounter = new Writable({
      write(chunk, encoding, callback) {
        counter = counter + 1
        callback()
      },
      writev(chunks, callback) {
        counter = counter + chunks.length
        callback()
      }
    })
    fs.createReadStream('itcont.txt')
      .pipe(split())
      .pipe(linecounter)
    linecounter.on('finish', function() {
      console.log(counter)
    })

    NB : Der Code ist absichtlich so einfach wie möglich geschrieben. Globale Variablen sind schlecht!


    Was Sie beachten sollten:


    • split - npm ein Paket, das einen String-Stream als "Eingabe" empfängt - gibt einen String-Stream als "separate" Ausgabe zurück, die durch Zeilenumbrüche getrennt ist. Höchstwahrscheinlich als Implementierung eines Transformationsstroms erstellt. Wir leiten unseren ReadStream mit einer Datei hinein und leiten uns selbst in ...
    • Linecounter - Implementierung von WritableStream. Darin implementieren wir zwei Methoden: zum Verarbeiten von einem Stück (Chunk) und mehreren. Die "Zeile" in dieser Situation ist die Codezeile. Rückwärts - Hinzufügen der gewünschten Zahl zum Zähler. Es ist wichtig zu verstehen, dass in dieser Situation nicht die gesamte Datei in den Speicher geladen wird und die API alles für uns in "Teile" aufteilt, die für die Verarbeitung am bequemsten sind
    • "Beenden" - Ereignisse, die "auftreten", wenn die auf unserem ReadableStream eintreffenden Daten "enden". In diesem Fall verpflichten wir uns zur Eingabe von Zählerdaten

    Testen wir unsere Erstellung an einer großen Datei:


    > node linecounter.js
    13903993

    Wie Sie sehen können - alles funktioniert. Daraus können wir schließen, dass die Stream-API mit Dateien jeder Größe hervorragende Arbeit leistet und die Aussage des Autors des Posts, gelinde gesagt, nicht wahr ist. In ungefähr der gleichen Weise können wir jeden anderen Wert berechnen, der für das Problem erforderlich ist.


    Sagen Sie:


    • Möchten Sie lesen, wie Sie das Problem vollständig lösen und den resultierenden Code für die Wartung in eine bequeme Form bringen können?
    • Verwenden Sie die Stream-API und auf welche Schwierigkeiten sind Sie gestoßen?

    Jetzt auch beliebt: