Узел.потоки js против наблюдаемых
узнав о параметры, Я нахожу их очень похожими на узел.потоки в JS. Оба имеют механизм уведомления потребителя всякий раз, когда поступают новые данные, возникает ошибка или больше нет данных (EOF).
Я хотел бы узнать о концептуальных/функциональных различиях между ними. Спасибо!
1 ответ:
и параметры и узел.в JS это потоки позволяет решить ту же основную проблему: асинхронно обрабатывать последовательность значений. Основное различие между ними, я считаю, связано с контекстом, который мотивировал его появление. Этот контекст отражен в терминологии и API.
на параметры side у вас есть расширение для EcmaScript, которое представляет модель реактивного программирования. Он пытается заполните пробел между генерацией значений и асинхронностью минималистскими и композиционными концепциями
Observer
иObservable
.на узел.js и потоки сторона вы хотели создать интерфейс для асинхронной и производительной обработки сетевых потоков и локальных файлов. Терминология происходит из этого начального контекста, и вы получаете
pipe
,chunk
,encoding
,flush
,Duplex
,Buffer
и т. д. Имея прагматический подход, который обеспечивает явную поддержку для конкретных случаев использования вы теряете некоторую способность составлять вещи, потому что это не так единообразно. Например, вы используетеpush
наReadable
Stream иwrite
наWritable
хотя, концептуально, вы делаете то же самое: публикуете значение.Итак, на практике, если вы посмотрите на концепции, и если вы используете опцию
{ objectMode: true }
, вы можете соответствоватьObservable
СReadable
Stream иObserver
СWritable
поток. Вы даже можете создать несколько простых адаптеров между ними модели.var Readable = require('stream').Readable; var Writable = require('stream').Writable; var util = require('util'); var Observable = function(subscriber) { this.subscribe = subscriber; } var Subscription = function(unsubscribe) { this.unsubscribe = unsubscribe; } Observable.fromReadable = function(readable) { return new Observable(function(observer) { function nop() {}; var nextFn = observer.next ? observer.next.bind(observer) : nop; var returnFn = observer.return ? observer.return.bind(observer) : nop; var throwFn = observer.throw ? observer.throw.bind(observer) : nop; readable.on('data', nextFn); readable.on('end', returnFn); readable.on('error', throwFn); return new Subscription(function() { readable.removeListener('data', nextFn); readable.removeListener('end', returnFn); readable.removeListener('error', throwFn); }); }); } var Observer = function(handlers) { function nop() {}; this.next = handlers.next || nop; this.return = handlers.return || nop; this.throw = handlers.throw || nop; } Observer.fromWritable = function(writable, shouldEnd, throwFn) { return new Observer({ next: writable.write.bind(writable), return: shouldEnd ? writable.end.bind(writable) : function() {}, throw: throwFn }); }
вы, возможно, заметили, что я изменил несколько имен и использовал более простые понятия
Observer
иSubscription
, введенный здесь, чтобы избежать перегрузки ответственности, выполненной параметры наGenerator
. В основном,Subscription
позволяет отписаться отObservable
. В любом случае, с приведенным выше кодом вы можете иметьpipe
.Observable.fromReadable(process.stdin).subscribe(Observer.fromWritable(process.stdout));
по сравнению с
process.stdin.pipe(process.stdout)
, у вас есть способ объединить, фильтровать и преобразовывать потоки, которые также работает для любой последовательности данных. Вы можете достичь этого сReadable
,Transform
иWritable
потоки, но API предпочитает подклассы вместо цепочкиReadable
s и применение функций. НаObservable
модель, например, преобразование значений соответствует применению функции трансформатора к потоку. Он не требует нового подтипаTransform
.Observable.just = function(/*... arguments*/) { var values = arguments; return new Observable(function(observer) { [].forEach.call(values, function(value) { observer.next(value); }); observer.return(); return new Subscription(function() {}); }); }; Observable.prototype.transform = function(transformer) { var source = this; return new Observable(function(observer) { return source.subscribe({ next: function(v) { observer.next(transformer(v)); }, return: observer.return.bind(observer), throw: observer.throw.bind(observer) }); }); }; Observable.just(1, 2, 3, 4, 5).transform(JSON.stringify) .subscribe(Observer.fromWritable(process.stdout))
вывод? Легко ввести реактивную модель и все еще идет на это. Но если вам действительно нужно отправить содержимое файла клиенту, разобраться с кодировкой и заархивировать его, тогда поддержка есть, в NodeJS, и она работает довольно хорошо.