Slide 1

Slide 1 text

Node.JS Streams с применением Артём Бей для KharkivJS 1

Slide 2

Slide 2 text

2 Артём Бей разработчик интерфейсов в YouScan и LeadScanner в твиттере @defly_self сервис поиска клиентов в социальных сетях сервис мониторинга чего угодно в тех же сетях

Slide 3

Slide 3 text

Поток это последовательность данных, существующая во времени. 3

Slide 4

Slide 4 text

Поток это последовательность данных, существующая во времени. не путать с потоками которые threads 4

Slide 5

Slide 5 text

Интерфейс для работы с вводом/выводом. 5

Slide 6

Slide 6 text

00000 == V8 + I/O 6

Slide 7

Slide 7 text

Ввод/вывод в Node.JS • fs • http • net • process.stdin • process.stdout 7

Slide 8

Slide 8 text

fs.readFile('/etc/passwd',  function  (err,  data)  {      if  (err)  throw  err;      console.log(data);//'qwerty'   }); fs.writeFile('message.txt',  ‘Oh  my  Node',     function  (err)  {      if  (err)  throw  err;      console.log(‘Fuck  yeah!’);   }); http.request(options,  function(res)  {      res.on('data',  function  (chunk)  {          console.log('BODY:  '  +  chunk);      });   }); var  net  =  require('net');   var  client  =  net.connect({...},          function()  {                  console.log('connected  to  server!');                  client.write('world!\r\n');          });   client.on('data',  function(data)  {          console.log(data.toString());          client.end();   });   client.on('end',  function()  {          console.log('disconnected  from  server');   }); Код разный, но есть что-то общее 8

Slide 9

Slide 9 text

Readable и Writable 9

Slide 10

Slide 10 text

В чём профит? 1. Один интерфейс 2. Комплементарность 3. Соглашение для вашего I/O кода 4. Unix way 10

Slide 11

Slide 11 text

pipe request(...).pipe(zlib.createGunzip()).pipe(process.stdout) 11

Slide 12

Slide 12 text

Популярные инструменты • request • socksjs • gulp • browserify • your-lib 12

Slide 13

Slide 13 text

Более удобный API • through • event-stream • 100500 утилит в npm • highland 13

Slide 14

Slide 14 text

Highland Библиотека для работы с потоками, в том числе потоками высшего порядка • _.() для потоков • От создателя node-async Caolan McMahon • 1172 звёзды на github* *актуально на 6 февраля 2015 14

Slide 15

Slide 15 text

• Chain API и не только • Генерация стримов из многих источников • Методы для преобразование стрима • Стримы высшего порядка • Более приятная обработка ошибок • Примочки из функционального программирования 15

Slide 16

Slide 16 text

API var  r  =  request.post(...);   _(r)          .invoke('toString',  ['utf8'])          .split("\r\n")          .map(JSON.parse)          .filter(maybeSpam)          .pluck("text")          .errors(_.log)          .each(_.log); 16

Slide 17

Slide 17 text

Источники стримов • массивы • Readable стримы • events • callback(err, data) • promise • собственный генератор 17

Slide 18

Slide 18 text

_('message',  client)   _([1,  2,  3,  4])   _(dbReadableStream)   _.wrapCallback(fs.readFile);   _(fetch('/api/foo'))   function  getData(filename)  {          return  _(function(push,  next)  {                  fs.readFile(filename,  function(err,  data)  {                          push(err,  data);                          push(null,  _.nil);                  });          });   }; 18

Slide 19

Slide 19 text

Что можно делать со стримом? • Split • Фильтровать (find, where …) • Сворачивать (reduce, scan, group, uniq etc) • Трансформировать (map, pluck, pick etc) • throttle, debounce, ratelimit 19

Slide 20

Slide 20 text

Стримы высшего порядка 20 • Копирование, конкатенация, объединение • Map/Filter стрима функциями которые возвращают стрим • Выравнивание вложенных стримов

Slide 21

Slide 21 text

var  nums  =  _(          _([1,  2,  3]),          _([4,  _([5,  6])  ])   );   nums.flatten();    //  =>  1,  2,  3,  4,  5,  6 _([1,  2]).concat([3,  4])    //  =>  1,  2,  3,  4 _(filenames).flatFilter(checkExists)   //  true  false  true  ...   _(filenames).flatMap(readFile)   //contents  of  files  in  order

Slide 22

Slide 22 text

Control-flow 22 Обработка источников стримов последовательно и параллельно _(filenames).map(readFile).series()     //almost  same  _(filenames).flatMap(readFile)   //  read  from  up  to  10  files  at  once   _(filenames).map(readFile).parallel(10);

Slide 23

Slide 23 text

Обработка ошибок getDocuments.errors(function  (err,  push)  {          if  (err.statusCode  ===  404)  {                  //  not  found,  return  empty  doc                  push(null,  {});          }  else  {                  //  otherwise,  re-­‐throw  the  error                  push(err);          }   }) по человечески:)

Slide 24

Slide 24 text

Почитать по теме • Stream handbook от substack • Документация по Highland • Статью Callback Hell vs. Async vs. Highland • https://github.com/caolan/highland/blob/ master/test/test.js 24

Slide 25

Slide 25 text

Спасибо за внимание:) Задавайте вопросы! 25