0

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

我使用 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 试图一次返回整个响应时,会导致内存问题。

4

2 回答 2

0

如果我是正确的,基本上你的问题是 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);
    });


});
于 2017-10-26T11:47:47.167 回答
0

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

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

items.insert('a bunch of items ...');
于 2017-10-23T13:53:14.567 回答