【问题标题】:NodeJS - How can I stream a response using an in memory DB?NodeJS - 如何使用内存数据库流式传输响应?
【发布时间】:2017-10-23 13:07:30
【问题描述】:

如何使用内存数据库流式传输响应?

我使用 Loki JS 作为内存数据库。有一个特定的资源,我必须返回一个表的全部内容(不能分页),并且该表可以增长到 500,000 项左右,大约是 300mb。

在其他情况下,我使用 fs.createReadStream 获取文件并将其流式传输回给用户:

fs.createReadStream('zips.json')
  .on('data', function() {
    res.write(...)
  })
  .on('end', function() {
    res.end();
  })

这对大文件非常有效,但我怎样才能使用内存数据库做一些等效的事情呢?

const items = lokiDb.addCollection('items');
items.insert('a bunch of items ...');

// I would now like to stream items via res.write
res.write(items)

目前,res.write(items) 会导致内存问题,因为 Node 试图一次返回整个响应。

【问题讨论】:

    标签: node.js stream lokijs


    【解决方案1】:

    据我所知,Loki 中没有本地流提供程序,尽管我可能错过了它。您可能想要做的是收听集合上的“插入”事件并编写它,如下所示:

    const items = lokiDb.addCollection('items');
    items.on('insert', (results) => {
      res.write(results);
    });
    
    items.insert('a bunch of items ...');
    

    【讨论】:

      【解决方案2】:

      如果我是正确的,基本上你的问题是 readStreams 只从文件中读取,而你想从内存中的数据结构中读取。一个解决方案可能是定义自己的 readStream 类,稍微修改原型 stream.Readable._read 方法:

      var util = require('util');
      var stream = require('stream');
      
      "use strict";
      var begin=0, end=0;
      var options = {
          highWaterMark:  16384,
          encoding:       null,
          objectMode:     false
      };
      
      util.inherits(InMemoryStream, stream.Readable);
      
      function InMemoryStream(userDefinedOptions, resource){
      
          if (userDefinedOptions){
              for (var key in userDefinedOptions){
                  options.key = userDefinedOptions[key];
              }
          }
      
          this.resource = resource;
          stream.Readable.call(this, options);
      }
      
      
      InMemoryStream.prototype._read = function(size){
      
          end += size;
          this.push(this.resource.slice(begin, end));
          begin += size;
      
          }
      
      exports.InMemoryStream = InMemoryStream;    
      exports.readStream = function(UserDefinedOptions, resource){
          return new InMemoryStream(UserDefinedOptions, resource);
      }
      

      您将内存中的数据结构(在以下示例中为数组)转换为 readStream,并将其通过管道传输到 writeStream,如下所示:

      "use strict";
      
      var fs = require('fs');
      var InMemoryStream = require('/home/regular/javascript/poc/inmemorystream.js');
      
      var stored=[], writestream, config={};
      
      config = {
          encoding: null,
          fileToRead: 'raphael.js',
          fileToWrite: 'secondraphael.js'
      }
      
      fs.readFile(config.fileToRead, function(err, data){
          if (err) return console.log('Error when opening file', err);
          stored = data;
      
          var inMemoryStream = InMemoryStream.readStream({encoding: config.encoding}, stored);
          writestream = fs.createWriteStream(config.fileToWrite);
          inMemoryStream.pipe(writestream);
      
          inMemoryStream.on('error', function(err){
              console.log('in memory stream error', err);
          });
      
      
      });
      

      【讨论】:

      • 对不起,愚蠢的例子;没有想清楚:当然存储只是变成了一个缓冲区。将原型中的 push() 更改为如下所示,您应该没问题,至少对于基于字符串的数据: this.push(this.resource.join(' ').slice(begin, end));
      猜你喜欢
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多