Надеюсь, что я правильно задаю вопрос, но по существу, есть ли способ в NodeJS, чтобы модуль CommonJS возвращал поток данных вместо финализированного фрагмента данных после (длинного) вычисления? Предполагая, что существует несколько способов, каковы эти методы?
Например, скажем, что у меня есть функция findPrimes
, написанная как модуль CommonJS:
/**
* @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;
};
Как вы можете видеть, эта функция возвращает массив всех простых чисел, меньших, чем его вход. Он возвращает массив после вычисления всех этих чисел.
Итак, скажем, я использую этот модуль в сценарии узла
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...
Хотя это работает, в идеале я хотел бы, чтобы программа начала записывать числа, которые она вычислила, прежде чем она закончится.
Поэтому моя программа все равно займет некоторое время, но она начнет выводить информацию на экран намного быстрее, чем "сначала вычислить ВСЕ, а затем вывести ВСЕ результаты".
Каков наилучший способ достижения этого эффекта? Потоки? Обещания?
Спасибо, я благодарен всем за это.
Вам придется использовать класс Stream из nodejs, и метод должен экспортировать обратный вызов с потоком, как отмечали комментарии:
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');
});
});
Для этого вы можете использовать модуль stream
Node.js. Трудно ответить на ваш вопрос в нескольких строках кода, но если вам действительно интересно, как работают потоки, посмотрите на это видео (это я рассказываю о потоках Node.js на собрании Node.js в Мюнхене, Германия).
В качестве альтернативы вы можете использовать функцию генератора с yield
, но это также трудно объяснить с нуля в нескольких строках.
В любом случае, потоки и функции генератора - это те термины, которые вы должны искать.