Как использовать преобразование узла для преобразования одного объекта в другой
Я новичок в потоках 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);