简体   繁体   English

在 NodeJS 中使用流

[英]Using streams in NodeJS

I'm trying to build an API in Nodejs that will stream the output of a query that is executed against a vertica DB.我正在尝试在 Nodejs 中构建一个 API,它将流式传输针对 vertica DB 执行的查询的输出。

The vertica db driver in Nodejs exposes unbuffered query interface that I'm using. Nodejs 中的 vertica db 驱动程序公开了我正在使用的无缓冲查询接口。 For more details about that please see: https://github.com/wvanbergen/node-vertica有关更多详细信息,请参阅: https : //github.com/wvanbergen/node-vertica

Following is my code:以下是我的代码:

var vertica = require('vertica');
var Readable = require('stream').Readable;
var rs = new Readable;

var conn = vertica.connect( {
    host: 'hostname',
    user: 'user',
    password: 'password',
    database: 'verticadb'    
});


var q = conn.query('select * from table');

q.on('row', function(row) {
    rs.push(row.join(',') + "\n");
});

q.on('end', function(status) {
    rs.push(null);
    rs.pipe(process.stdout);
    conn.disconnect();
});

q.on('error', function(err) {
    conn.disconnect();
});

It does return the appropriate output, but my understanding is that it actually buffers up the output of row.join(',') + "\\n" and only pipes it out to stdout once all rows are read.它确实返回了适当的输出,但我的理解是它实际上缓冲了row.join(',') + "\\n"的输出,并且只有在读取所有行后才将其输出到 stdout。 My objective is to pipe each row out as soon as it is read.我的目标是在读取每一行后立即将其输出。 How should I modify my code to make it work ?我应该如何修改我的代码以使其工作? You can replace the vertica "row" event with anything comparable.您可以将 vertica“row” 事件替换为任何可比较的事件。

Addendum附录

I've managed to make it work using what is called "classic readable streams" based on the documentation found on: https://github.com/substack/stream-handbook .我已经根据在以下位置找到的文档设法使用所谓的“经典可读流”使其工作: https : //github.com/substack/stream-handbook

The code for this:代码:

var vertica = require('vertica');
var Stream = require('stream');
var stream = new Stream;
stream.readable = true;

var conn = vertica.connect( {
    host: 'hostname',
    user: 'user',
    password: 'password',
    database: 'verticadb'
});


var q = conn.query('select * from affiliate_manager_2');

q.on('row', function(row) {
    stream.emit('data', row.join(',') + "\n");
});

q.on('end', function(status) {
    stream.emit('end'); 
    conn.disconnect();
});

q.on('error', function(err) {
    conn.disconnect();
});

stream.pipe(process.stdout);

However it is the "old" way of doing it, and I would like to know how to do it using the "new way".然而,这是做这件事的“旧”方式,我想知道如何使用“新方式”来做。

Readable is “abstract”. Readable是“抽象的”。 It's looking for a function called _read , which is not defined on the default implementation.它正在寻找一个名为_read的函数,该函数未在默认实现中定义。 Without it, it just buffers every push(chunk) until it sees push(null) .没有它,它只会缓冲每个push(chunk)直到它看到push(null) That's the behavior you're seeing in your example.这就是您在示例中看到的行为。

To get the behavior you want, just add a _read function!要获得您想要的行为,只需添加一个_read函数!

Here's an example you can adapt to your database:这是一个可以适应您的数据库的示例:

var Readable = require('stream').Readable;

var stream = new Readable;

stream._read = function () {
  var query = …;
  query.on('row', function (row) {
    stream.push(JSON.stringify(row) + '\n');
  });
  query.on('end', function () {
    stream.push(null);
  });
  stream._read = function () {};
};

stream.pipe(process.stdout);

Further reading:进一步阅读:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM