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

时间:2017-10-23 13:07:30

标签: node.js stream lokijs

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

我正在使用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尝试立即返回整个响应。

2 个答案:

答案 0 :(得分:0)

据我所知,Loki没有本地流提供商,但我可能错过了它。您可能想要做的是听取'插入'集合上的事件并写下,如下:

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

items.insert('a bunch of items ...');

答案 1 :(得分: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);
    });


});