Express. js: поток результатов из Mon go и неблокирующая сериализация - PullRequest
2 голосов
/ 10 июля 2020

Я пытаюсь обновить этот ответ , чтобы он не зависел от библиотеки JSONStream , которая больше не поддерживается. У нас есть:

Comment.find()
  .cursor()
  .pipe(JSONStream.stringify())
  .pipe(res.type('json'))

Он использует Mon goose .cursor(), который возвращает Node.js -совместимый читаемый поток , но я открыт для использования собственного mon go driver.

Теперь мой первый вопрос: кто-нибудь все еще использует потоки Node.js или вы в настоящее время должны использовать JavaScript Итераторы и генераторы?

Если да, то я думаю, я смогу преобразовать курсор в итератор и преобразовать каждый фрагмент в JSON отдельно. (Хотя рекомендации библиотеки, которые выполняют обработку ошибок et c. Приветствуются, даже если здесь не указано c, а не суть этого вопроса).

Но как мне сделать поток итератора в результат express. js?

Я не смог найти никакой документации по этому поводу (хотя не смог найти документацию по res, являющемуся потоком с возможностью записи, хотя он работает). Я даже на правильном пути с моим мышлением здесь?

Изменить:

Между тем, я провел еще несколько исследований и нашел следующие библиотеки:

1 Ответ

1 голос
/ 13 июля 2020

Edit : добавлен настраиваемый шаг преобразования в строку.

Объект res в ExpressJS является подклассом с возможностью записи из http.ServerResponse , и может передаваться по конвейеру.

Я обычно подключаю этот поток данных, используя встроенную поддержку NodeJS 'для преобразования итератора в читаемый и использую stream.pipeline для обработки исключений.

Обратите внимание, что больше нет необходимости преобразовывать курсор в читаемый в NodeJS v13 +, поскольку stream.pipeline теперь принимает асинхронные c итераторы вместо потока.

Обратите внимание, что использование stringify() излишне, если возможно напрямую использовать Mon goose s Lean () . Lean выдаст JSON данных.

import stream from "stream";
import util from "util";

function handler(req, res, next){
  try {
    // init the cursor
    const cursor = Comment.find().lean(); // "lean" will emit json data
    const readable = stream.Readable.from( cursor );
    // promisifying the pipeline will make it throw on errors
    await util.promisify(stream.pipeline)( readable, res.type('json') );
    next();
  }
  catch( error ){
    next( error );
  }
}

С настраиваемой строковой настройкой в ​​NodeJS v13 +:


import stream from "stream";
import util from "util";

function handler(req, res, next){
  try {
    // init the cursor
    const cursor = Comment.find().lean(); // "lean" will emit json data
    const readable = stream.Readable.from( cursor );
    // promisifying the pipeline will make it throw on errors
    await util.promisify(stream.pipeline)( 
      readable,
      // Custom "stringifying" using an async iterator
      async function*( source ){
        // Add some output before the result from mongodb. Typically, this could be information about 
        // the number of results in a REST API.
        yield "Appended"

        for await (const comment of source ){
          // Emit a "projection" of the data retrieved from MongoDB 
          yield {
            text: comment.text,
            // Add a new property:
            newProperty: true
          }
        }
        // Add some final data to the response. In a REST API, this might be the closing bracket of an array "]".
        yield "Prended"
      },
      // the stringified data is then piped to express' res object
      res.type('json') 
    );
    next();
  }
  catch( error ){
    next( error );
  }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...