Как использовать преобразование узла для преобразования одного объекта в другой

Я новичок в потоках Node и пытаюсь понять, почему все работает не так, как ожидалось. Я просто тренируюсь и хочу сделать глупое преобразование.

interface MyTransformStreamOptions {
  [key: string]: any
}

class MyTransformStream extends Transform {
  constructor(options) {
    options.readableObjectMode = true;
    options.writableObjectMode = true;

    super(options);
  }

  _transform(chunk, encoding, callback) {
    console.log('encoding: ' + encoding);

    // chunk should be an object here, due to
    // readableObjectMode = true right?

    const newObj = {};

    for (const [key, value] of Object.entries(chunk)) {
      console.log(`[key, value]: [${key}, ${value}]`);
      newObj['aa' + key] = 'bb' + value;
    }

    callback(null, newObj);
  }
}

const myTransformStream = new MyTransformStream({} as MyTransformStreamOptions);

process.stdin
  .pipe(myTransformStream)
  .pipe(process.stdout);

Наконец, я запускаю скрипт и ввожу его через stdin:

{ car: 'honda', truck: 'mazda' }

а также я попробовал:

"{ car: 'honda', truck: 'mazda' }"

Но цикл обрабатывает блок как строку, а не как объект. Итак, я вижу вывод как:

[key, value]: [0, 123]
[key, value]: [1, 32]
...etc...

Я пробовал различные комбинации:

options.readableObjectMode = true/false;
options.writableObjectMode = true/false;

А также в _transform() с помощью:

const obj = JSON.parse(chunk.toString());

но obj никогда не является объектом и всегда является строкой.

Моя цель - получить объект в поток преобразования, изменить его и вывести. Но я зацикливаюсь только на строках, которые не могу преобразовать в объекты даже с JSON.parse(),

Куда я здесь не так?

Обновление - Частичное решение

Проблема была с моим использованием JSON.parse(), Я пытался разобрать:

{ car: 'honda', truck: 'mazda' }

Который является действительным JS, но не действительным JSON, да!

Тем не менее, большая проблема все еще остается. Я установил поток преобразования в: writableObjectMode = true, но, когда я делаю:

callback(null, newObj);

Я получаю ошибку:

TypeError: Invalid data, chunk must be a string or buffer, not object

Если я сделаю:

callback(null, JSON.stringify(newObj));

все работает как положено.

Тем не менее, не должно ли это работать без строковых, учитывая, что я настроил вещи в режиме объекта?

2 ответа

Итак, основные проблемы с моим кодом - это использование stdin а также stdout, Это потоки, которые работают в режиме строки / буфера. Используя их как есть, передача stdin в поток будет осуществляться в режиме строки / буфера, а не в режиме объекта. То же самое относится к стандартному выводу.

Я проверил свою гипотезу, создав читаемый поток в объектном режиме, который эмулировал мой ввод stdin, который я вводил через _read() метод, а затем мой поток преобразования преобразует кусок как объект, который читаемый поток направил в него.

Канал к стандартному выходу все еще терпел неудачу, поскольку он принимает объекты из коробки. Я подтвердил это, создав другой поток преобразования, который просто преобразовал объект в строку с помощью JSON.stringify() и тогда stdout снова был счастлив.

Все проблемы, с которыми у меня были "режимы чтения / записи", были просто потому, что у меня были stdin и stdout по обе стороны от моего потока преобразования.

Объектный режим не преобразует поток из буфера (это буфер, а не строка) в объект, он просто позволяет типу данных иметь типы, отличные от буфера или строки. Вам необходимо использовать поток преобразования для преобразования буфера stdin в объект, такой как:

const ndjson = require('ndjson');

. . .

process.stdin
  .pipe(ndjson.parse())
  .pipe(myTransformStream)
  .pipe(process.stdout);
Другие вопросы по тегам