Я новичок в потоках 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.info('encoding: ' + encoding);
// chunk should be an object here, due to
// readableObjectMode = true right?
const newObj = {};
for (const [key, value] of Object.entries(chunk)) {
console.info(`[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);
Наконец, я запускаю скрипт и ввожу его через стандартный ввод:
{ 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));
все работает как положено.
Однако разве это не должно работать без строкового преобразования, учитывая, что я настроил все в объектном режиме?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Объектный режим не преобразует поток из буфера (это буфер, а не строка) в объект, он просто позволяет типу данных быть типами, отличными от буфера или строки. Вам необходимо использовать поток преобразования для преобразования буфера стандартного ввода в объект, например:
const ndjson = require('ndjson');
. . .
process.stdin
.pipe(ndjson.parse())
.pipe(myTransformStream)
.pipe(process.stdout);
Итак, основные проблемы с моим кодом - это использование stdin и stdout. Это потоки, которые работают в строковом / буферном режиме. Используя их как есть, конвейерный ввод stdin в поток будет передаваться в строковом / буферном режиме, а не в объектном режиме. То же самое и с stdout.
Я проверил свою гипотезу, создав читаемый поток в объектном режиме, который имитировал мой ввод stdin, который я вводил с помощью метода _read(), а затем заставил мой поток преобразования преобразовать кусок как объект, который читаемый поток передал в него.
Труба к стандартному выходу все еще терпела неудачу, поскольку принимала объекты из коробки. Я подтвердил это, создав другой поток преобразования, который просто преобразовал объект в строку через JSON.stringify(), и затем stdout снова был счастлив.
Все проблемы, которые у меня были с «режимами чтения / записи объекта», были просто потому, что у меня были stdin и stdout по обе стороны от моего потока преобразования.
Спасибо за совет, но использование ndjson просто не меняет того поведения, которое я наблюдаю. Кроме того, что касается потока, являющегося буфером, строки vs и т. д., Из документации Node: chunk <Buffer> | <строка> | <any> Фрагмент, который нужно преобразовать. Всегда будет буфером, если для параметра decodeStrings не задано значение false или поток не работает в объектном режиме. И в другом месте на той же странице документа: все потоки, созданные API-интерфейсами Node.js, работают исключительно со строками и объектами Buffer (или Uint8Array). Однако реализации потоков могут работать с другими типами значений JavaScript.