拥有节点模块 return 数据 "stream" 的技术?
Techniques for having a node module return a "stream" of data?
我希望我问的问题是正确的,但本质上,NodeJS 有没有办法让 CommonJS 模块 return 经过(长)计算后的数据流而不是最终确定的数据块?假设有不止一种方式,那些技术是什么?
例如,假设我有一个 findPrimes
函数,写成 CommonJS 模块:
查找-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;
};
如您所见,此函数 return 是一个包含所有小于其输入的素数的数组。它 return 是数组 在 之后它计算了所有这些数字。
所以,假设我要在节点脚本中使用这个模块
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
时,我得到以下(预期)输出:
$ 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...
虽然这可行,但理想情况下我希望程序在完成之前开始写出它计算出的数字。
所以我的程序仍然需要一段时间才能 运行,但它开始向屏幕输出信息的速度比 "compute EVERYTHING first, then output ALL results" 快得多。
实现这种效果的最佳方法是什么? Streams? Promises?
我愿意接受任何和所有的技术,谢谢。
您可以为此使用 Node.js 的 stream
模块。很难在几行代码内回答您的问题,但如果您 真的 对流的工作原理感兴趣,请查看 this video(这是我在演讲关于 Node.js 在 Node.js 德国慕尼黑聚会上的直播。
或者,您可以使用带有 yield
的生成器函数,但这也很难用几行从头开始解释。
无论如何,streams 和 generator functions 是您应该查找的术语。
您必须使用来自 nodejs 的 Stream class,并且该方法应该导出带有流的回调,如评论所述:
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');
});
});
我希望我问的问题是正确的,但本质上,NodeJS 有没有办法让 CommonJS 模块 return 经过(长)计算后的数据流而不是最终确定的数据块?假设有不止一种方式,那些技术是什么?
例如,假设我有一个 findPrimes
函数,写成 CommonJS 模块:
查找-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;
};
如您所见,此函数 return 是一个包含所有小于其输入的素数的数组。它 return 是数组 在 之后它计算了所有这些数字。
所以,假设我要在节点脚本中使用这个模块
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
时,我得到以下(预期)输出:
$ 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...
虽然这可行,但理想情况下我希望程序在完成之前开始写出它计算出的数字。
所以我的程序仍然需要一段时间才能 运行,但它开始向屏幕输出信息的速度比 "compute EVERYTHING first, then output ALL results" 快得多。
实现这种效果的最佳方法是什么? Streams? Promises?
我愿意接受任何和所有的技术,谢谢。
您可以为此使用 Node.js 的 stream
模块。很难在几行代码内回答您的问题,但如果您 真的 对流的工作原理感兴趣,请查看 this video(这是我在演讲关于 Node.js 在 Node.js 德国慕尼黑聚会上的直播。
或者,您可以使用带有 yield
的生成器函数,但这也很难用几行从头开始解释。
无论如何,streams 和 generator functions 是您应该查找的术语。
您必须使用来自 nodejs 的 Stream class,并且该方法应该导出带有流的回调,如评论所述:
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');
});
});