【问题标题】:Techniques for having a node module return a "stream" of data?让节点模块返回数据“流”的技术?
【发布时间】:2017-11-10 15:55:08
【问题描述】:

我希望我问的问题是正确的,但本质上,NodeJS 中有没有办法让 CommonJS 模块返回数据流而不是最终确定的(长时间)计算后的数据块?假设有不止一种方法,那么这些技术是什么?

例如,假设我有一个 findPrimes 函数,写成 CommonJS 模块:

find-primes.js

/**
 * @module  findPrimes
 * @param {int} n - Find all primes less than this number
 * @return {array}
 */
module.exports = function(n) {
    if (n < 2) {
        return [];
    } else if (n === 2) {
        return [2];
    }

    var primes = [2];

    for (let i = 3; i < n; i += 2) {
        let is_prime = true;
        let sq = Math.ceil(Math.sqrt(i));

        for (let t = 2; t <= sq; t++) {
            if (i % t === 0) {
                is_prime = false;
                break;
            }
        }

        if (is_prime) {
            primes.push(i);
        }
    }

    return primes;
};

如您所见,此函数返回一个由所有小于其输入的素数组成的数组。它在计算所有这些数字之后返回数组

所以,假设我要在节点脚本中使用这个模块

index.js

const primes = require('./find-primes.js');

// Usage: `node index.js <num>`
let primes_less_than = process.argv[2];

console.log(primes(primes_less_than));

当我以 25 的 arg 运行上述脚本时,我得到以下(预期的)输出:

$ node index.js 25
[ 2, 3, 5, 7, 11, 13, 17, 19, 23 ]

但是,假设我通过了一个更大的数字,比如 10,000,000

$ node index.js 10000000
# Takes a while to run before outputting the numbers...

虽然这可行,但理想情况下,我希望程序在完成之前开始写出它计算出的数字。

所以我的程序仍然需要一段时间才能运行,但它会比“先计算所有内容,然后输出所有结果”更快地开始向屏幕输出信息。

实现这种效果的最佳方法是什么? Streams? Promises?

我愿意接受任何和所有这方面的技术,谢谢。

【问题讨论】:

  • 通过回调可能吗? (最简单的不是最好的)
  • 你必须使用 Stream nodejs 类

标签: javascript node.js npm node-streams


【解决方案1】:

您可以为此使用 Node.js 的 stream 模块。几行代码很难回答您的问题,但如果您真的对流的工作原理感兴趣,请查看this video(这是我在谈论 Node.js 流在德国慕尼黑举行的 Node.js 聚会上)。

或者,您可以使用带有 yield 的生成器函数,但这也很难用几行代码从头开始解释。

无论如何,streamsgenerator functions 是您应该寻找的术语。

【讨论】:

  • 我猜如果 OP 知道流是什么,那么 OP 也确实知道如何使用回调......?
  • > 流和生成器函数是您应该寻找的术语。谢谢,有时间我也会看那个视频的。基本上,我尝试搜索处理“显示通过节点模块计算的部分数据”的技术,并且流似乎出现了,但我找不到任何好的示例(大多数处理 HTTP 请求)。我想要更舒适地编写适当的节点模块,所以这就是我正在处理的上下文。
  • 顺便说一句:在这次演讲中,我有一个如何使用流计算素数的示例……;-)))……从 36:09 开始 - youtu.be/QgEuZ52OZtU?t=36m9s
  • 谢谢你的视频,我最后看了大部分。信息量很大!
  • 非常感谢您的好评 :-)
【解决方案2】:

您必须使用 nodejs 中的 Stream 类,并且该方法应导出带有流的回调,如评论所述:

const stream = require('stream');

function getPrimesStream(n, cb) {
    const primesStream = new stream.Stream();
    cb(null, primesStream);
    if (n >= 2) {
        primesStream.emit('data', 2);
    }

    const primes = [2];

    for (let i = 3; i < n; i += 2) {
        let isPrime = true;
        const sq = Math.ceil(Math.sqrt(i));

        for (let t = 2; t <= sq; t += 1) {
            if (i % t === 0) {
                isPrime = false;
                break;
            }
        }

        if (isPrime) {
            primesStream.emit('data', i);
            primes.push(i);
        }
    }

    return primes;
}

getPrimesStream(1000, function (err, stream) {
    stream.on('data', function (data) {
        console.log(data);
    });
    stream.on('end', function() {
        console.log('finished');
    });
});

【讨论】:

    猜你喜欢
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2011-12-24
    • 2017-05-26
    • 2013-07-12
    • 1970-01-01
    相关资源
    最近更新 更多