Новости‎ > ‎

Nodejs Buffers для выгрузки данных POST запросов

Отправлено 23 февр. 2017 г., 11:48 пользователем Denis Baskovsky   [ обновлено 23 февр. 2017 г., 12:34 ]
Как-то раз, за обсуждением Idris ЯП с коллегой, зашла речь про графики plotly. Очередное подделие вызвало у меня неподдельную усмешку. Ещё бы! Что можно ожидать от ещё одного велосипедного чарта, содержащего в себе d3 и webgl? Правильно, валялся бы этот велосипед в бездне гитхаба, если бы у меня получилось установить chartjs-node. Но что-то мой химерный ubuntu-windows терминал, о котором я как раз недавно сделал обзор на моё блоге, не давал пакету установится, выплёвывая свою ругань на node-gyp. Python'ячьи ошибки не забота фронтмэна! Подакдакав, нашёл nodejs враппер plotly, под платный REST-API сервис https://plot.ly/, у которого по нынешним маркетинговым уловкам, конечно же был OpenSource вариант. Он то мне и подошёл. Прицепив его к своему простенькому боту всё было здорово, пока не вспомнилось что бэкэнд бота лежит на Heroku, а там фишка с fs.createWriteStream() не срабатывает по понятным знатоку SaSS-причинам. Задача вроде плёвая: из результата POST-запроса достать res:
https.request(options, function handleResponse(res) {
  if (res.statusCode !== 200) {
    callback(null, res);
});

Вот только я не знаток днища, и сразу не понял что написанный в доки невнятный imageStream (по-сути res выше) на самом деле является IncomingMessage, и если не следовать доки с их:
var fileStream = fs.createWriteStream('1.png');
imageStream.pipe(fileStream);

Без моих знаний о стримах понимать что происходит было сложно, типичный кейс с Stack Overflow Driven Development не прокатывал, потому что Stackoverflow уже был засран этим нубским говнищем, и искать что-либо нормальное было нереально. Потому залип в нодовские доки, чтобы понять как работают эти их хитрые стримы. 

Скажу, они работают круто, но сложно. Всякие пайпы, события close, end и разделение на секции Readable и Writable. Итогом стал нижеследующий код, смысл которого в том, чтобы через Writable стрим запайпить тот самый imageStream, данные которого можно будет прочитать в ws._write через чанк. Главная трабла, что привычный механизм добавления чанков через строковую переменную здесь не работает, важно обязательно добавлять невредимый чанк в своем формает Int8Array. Я это сделал через buffers. Затем у imageStream появляется возможность уловить события end в котором складываем все собранные чанки в один буфер и посылаем куда следует. 

const Writable = stream.Writable;
const ws = Writable();
const buffers = [];
ws._write = (chunk, enc, next) => {
  buffers.push(chunk);
  next();
};
imageStream.pipe(ws);
imageStream.on('end', () => {
  const photoBuffer = Buffer.concat(buffers);

  return bot.sendPhoto(chatId, photoBuffer, {
    caption: 'Photo'
  });
});

И теперь в моём боте есть отрендеренные графики. Mission Complete, Boss.
Comments