2017-06-20 26 views
5

I tarło proces potomny tak:Transform strumień poprzedzić ciąg do każdej linii

const n = cp.spawn('bash'); 

n.stdout.pipe(process.stdout); 
n.stderr.pipe(process.stderr); 

szukam transformacji strumień tak, że można poprzedzić coś jak „[procesowego dziecko]” na początek każda linia od dziecka, więc wiem, że stdio pochodzi od dziecka w porównaniu z procesem nadrzędnym.

Tak to będzie wyglądać:

const getTransformPrepender = function() : Transform { 
    return ... 
} 

n.stdout.pipe(getTransformPrepender('[child]')).pipe(process.stdout); 
n.stderr.pipe(getTransformPrepender('[child]')).pipe(process.stderr); 

czy ktoś wie, czy istnieje pakiet istniejących przekształcić tak, czyli jak napisać?

mam to:

import * as stream from 'stream'; 


export default function(pre: string){ 

    let saved = ''; 

    return new stream.Transform({ 

    transform(chunk, encoding, cb) { 

     cb(null, String(pre) + String(chunk)); 
    }, 

    flush(cb) { 
     this.push(saved); 
     cb(); 
    } 

    }); 

} 

ale obawiam się, że nie będzie działać w przypadkach krawędzi - gdzie jeden klocek rozerwanie nie może zawierać całą linię (dla bardzo długich linii).

Wygląda na to, że odpowiedź na to jest tutaj: https://strongloop.com/strongblog/practical-examples-of-the-new-node-js-streams-api/

ale z tego aneksu: https://twitter.com/the1mills/status/886340747275812865

Odpowiedz

5

Istnieje w sumie trzech przypadków, które należy prawidłowo obsłużyć:

  • Pojedynczy kawałek reprezentujący całą linię
  • Jeden kawałek reprezentujący wiele linii
  • Pojedynczy kawałek reprezentujący tylko część linia

Oto opis algorytmu, aby rozwiązać wszystkie trzy sytuacje

  1. Otrzymują porcję danych
  2. Skanowanie kawałek dla nowej linii
  3. Jak tylko nowa linia zostanie znaleziony, wziąć wszystko przed nim (w tym nowej linii) i wysłać go jako pojedynczy wpis linii z wszelkimi modyfikacjami trzeba
  4. powtarzać aż cała porcja została przetworzona (bez pozostałych danych) lub do momentu żadne dodatkowe znaki nowej linii zostały znalezione (niektóre dane pozostają, zapisać go na później)

i tu jest faktyczna realizacja z opisami dlaczego jest potrzebny itp.

Należy pamiętać, że ze względu na wydajność nie konwertuję buforów na klasyczne ciągi JS.

const { Transform } = require('stream') 

const prefix = Buffer.from('[worker]: ') 

const prepender = new Transform({ 
    transform(chunk, encoding, done) { 
    this._rest = this._rest && this._rest.length 
     ? Buffer.concat([this._rest, chunk]) 
     : chunk 

    let index 

    // As long as we keep finding newlines, keep making slices of the buffer and push them to the 
    // readable side of the transform stream 
    while ((index = this._rest.indexOf('\n')) !== -1) { 
     // The `end` parameter is non-inclusive, so increase it to include the newline we found 
     const line = this._rest.slice(0, ++index) 
     // `start` is inclusive, but we are already one char ahead of the newline -> all good 
     this._rest = this._rest.slice(index) 
     // We have a single line here! Prepend the string we want 
     this.push(Buffer.concat([prefix, line])) 
    } 

    return void done() 
    }, 

    // Called before the end of the input so we can handle any remaining 
    // data that we have saved 
    flush(done) { 
    // If we have any remaining data in the cache, send it out 
    if (this._rest && this._rest.length) { 
     return void done(null, Buffer.concat([prefix, this._rest]) 
    } 
    }, 
}) 

process.stdin.pipe(prepender).pipe(process.stdout) 
2

Jest to praca w toku:

https://github.com/ORESoftware/prepend-transform

ale jest ono przeznaczone do rozwiązać problem pod ręką tak:

import pt from 'prepend-transform'; 
import * as cp from 'child_process'; 

const n = cp.spawn('bash'); 

n.stdout.pipe(pt('[child stdout]')).pipe(process.stdout); 
n.stderr.pipe(pt('[child stderr]')).pipe(process.stderr); 
+0

, ale nie jest jeszcze kompletny, ponieważ nie obsługuje długich linii reprezentujących wiele wywołań ("danych"). –

+0

Ta implementacja nie jest kompletna i potrzebuję pomocy, aby była poprawna. –

+0

Myślę, że to ma odpowiedź - https://strongloop.com/strongblog/practical-examples-of-the-new-node-js-streams-api/ –