Instant data med Javascript Streams

Mikael Brevik

  • Konsulent hos BEKK
  • Bachelor fra HIST (2011), Master fra NTNU (2013).

Tidvis open source utvikler og standhaftig surfer på internett. Er å finne på Github som @mikaelbr og Twitter @mikaelbrevik. Regelmessig googler og Stackoverflow-leser.

Mikael Brevik

Agenda

  1. Hva er Javascript Streams?
  2. Kode!

Streams

Pipe Dream

Stammer fra UNIX versjon 8

Gjør blant annet at man kan gjøre I/O operasjoner chunk for chunk og ikke buffre hele innholdet i minnet.

Antall tegn i de første 9 linjene av index.html


            ➜ cat index.html | head -n9 | wc -c
    => 248

I Javascript

Node.js har en innebygd modul kalt streams.

Fremfor å bruke | bruker man .pipe()

4 forskjellige streams

  • Readable
  • Writable
  • Transform (through)
  • Duplex
// Echo application

var readable = process.stdin;
var writable = process.stdout;
readable.pipe(writable);
            

// Some implementation
var SHOUT = new stream.Transform;
process.stdin
        .pipe(SHOUT)
        .pipe(process.stdout);
            

var s1 = throughStream();
var s2 = throughStream();
s1.pipe(s2).pipe(s1);
            

To-veis kommunikasjon. Kan snakke begge veier.

Push streams vs Pull streams

Før Node.js 0.10, ble det brukt push streams, nå blir pull streams brukt (også kalt streams2)

Streams blir satt i compability mode (gjort om til push stream) om de har en eventlytter på data eller stream.resume() blir kalt

Push streams pusher data inn i mottaker (events).

Pull streams tillater mottaker å hente data selv.

Med pull streams kan en håntere dersom f.eks mottaker skriver data tregere enn sender.

Livekode!

Buffer av alt innhold


// Uten stream. Buffer alt til minnet.
// Krasjer om stor fil.
var data = fs.readFileSync(
    'data/compiled.data'
  );
            

The stream way


// Med stream. Start uthenting
// chunk for chunk med en gang
var readStream =
    fs.createReadStream('compiled.data');
readStream.pipe(process.stdout);
            

Mer avansert bruk


fs.createReadStream('data/compiled.data')
  .pipe(split(JSON.parse)) // split på \n, gjør om til obj.
  .pipe(through.obj(function (obj, enc, next) {
    obj.text && this.push(new Buffer(obj.text.replace(/\n/g, " ")) + "\n");
    next();
  }))

// ... neste slide
            

// ... fra forrige slide
.pipe(through.obj(function (tweet, enc, next) {
  if (tweet && /Sochi/ig.test(tweet) && !/^RT/.test(tweet)) {
    this.push(tweet);
  }
  next();
}))
.pipe(process.stdout)
            

Magi?


var decoder = new lame.Decoder(options);
var speaker = new Speaker(options);
var song =
  fs.createReadStream('data/sample.mp3');

song.pipe(decoder).pipe(speaker);
// => music
            

Kjapp oppsummering

  • Streams er veldig kraftig
  • Finnes 4 forskjellige: Readable, Writable, Transform og Duplex
  • Unngår å buffre mye data inn i minnet. Har lazy data.
  • Kan brukes til veldig mye

Spørsmål?

Ressurser og lenker