Задача кода, который вы показываете, состоит в том, чтобы собрать все данные из потока в один буфер, чтобы при возникновении события end
у вас были все данные.
request.on('data',...)
может излучать только один раз или сотни раз. Это зависит от размера данных, конфигурации объекта потока и типа потока позади него. Вы никогда не сможете с уверенностью предположить, что он будет излучать только один раз.
Вы можете делать что-либо с потоком запросов, например, направлять его через некоторые преобразования в объектном режиме и через некоторые другие потоки чтения. Похоже, что этот шаблон объединения никогда не нужен.
Этот шаблон объединения используется только тогда, когда вы пытаетесь получить все данные из этого потока в одну переменную. Весь смысл передачи в другой поток состоит в том, что вам не нужно извлекать все данные из одного потока перед отправкой в следующий поток. .pipe()
будет просто отправлять данные по мере их поступления в следующий поток. То же самое для преобразований.
Это потому, что поток запросов при обработке тел POST и PUT почти всегда генерирует только одно событие данных, потому что их полезная нагрузка намного ниже предела размера раздела чанка ?.
Вероятно, потому что полезная нагрузка ниже некоторого размера внутреннего буфера, и транспорт отправляет все данные одновременно, и вы не работаете по медленной линии связи и ... Дело в том, что вы не можете делать предположения о том, как будет много событий данных. Вы должны предположить, что их может быть больше одного, и что первое событие данных не обязательно содержит все данные или данные, разделенные хорошей границей. Многое может привести к тому, что входящие данные будут разбиты по-разному.
Имейте в виду, что readStream читает данные до тех пор, пока на мгновение не останется больше данных для чтения (до размера внутреннего буфера), а затем выдает событие data
. Он не ждет, пока буфер заполнится, прежде чем выдать событие data
. Таким образом, поскольку все данные на нижних уровнях стека TCP отправляются в пакетах, все, что требуется, - это мгновенная задержка доставки с некоторым пакетом, и поток не найдет больше данных, доступных для чтения, и выдаст событие data
. Это может произойти из-за способа отправки данных, из-за того, что происходит в транспорте, по которому передаются данные, или даже из-за локального управления потоком TCP, если много вещей происходит со стеком TCP на уровне ОС.
На практике, насколько большим должен быть кодированный в JSON-объект объект для потоковой передачи более чем в один блок данных?
Вы действительно не должны знать или заботиться, потому что вы ДОЛЖНЫ предполагать, что объект любого размера может быть доставлен более чем в одном data
событии. Вы, вероятно, можете с уверенностью предположить, что объект JSON, превышающий размер буфера внутреннего потока (который можно узнать, изучив код потока или изучив внутренние компоненты в отладчике), будет доставлен в нескольких событиях данных, но вы не можете предполагать обратное, потому что другие переменные, такие как связанные с транспортом вещи, которые могут привести к его разделению на несколько событий.
Мне кажется, что потокам objectMode не нужно беспокоиться о конкатенации, потому что, если вы имеете дело с объектом, он почти всегда не больше одного блока данных, который атомарно преобразуется в один объект? Я мог видеть проблему, если клиент загружал что-то вроде огромной коллекции (когда поток был бы очень полезен, если бы он мог анализировать отдельные объекты в коллекции и выдавать их один за другим или пакетами).
Потоки в объектном режиме должны выполнять свою собственную внутреннюю буферизацию, чтобы найти границы любых объектов, которые они анализируют, чтобы они могли излучать только целые объекты. На некотором низком уровне они объединяют буферы данных, а затем проверяют их, чтобы увидеть, есть ли у них еще целый объект.
Да, вы правы, если бы вы использовали поток объектного режима, а сами объекты были очень большими, они могли бы потреблять много памяти. Вероятно, это не самый оптимальный способ работы с данными такого типа.
Имеют ли потоковые преобразования objectMode внутреннюю логику для автоматической конкатенации вплоть до границ объекта?
Да, они делают.
К вашему сведению, первое, что я делаю, когда делаю http-запросы, это использую библиотеку request-promise
, чтобы мне не приходилось делать свою собственную конкатенацию. Это обрабатывает все это для вас. Он также предоставляет интерфейс на основе обещаний и около 100 других полезных функций, которые я считаю полезными.