关于终止动态构建的承诺序列
About terminating a dynamically constructed sequence of promises
我在 Node 中编写了一个脚本,用于迭代大型 MongoDB 集合,一次返回一定数量的文档。
集合的格式很简单:
{
name: 'One',
data: '...'
},
{
name: 'Two',
data: '...'
},
...
我正在使用 Q 库完成这项工作,使用一系列承诺 运行 一个接一个:
'use strict';
var Q = require('q');
var monk = require('monk');
var CHUNK_SIZE = 100;
var LIMIT = 1000;
var collection = monk('localhost/dictionary').get('entries');
var promiseFactory = function (j) {
return function (result) {
if (undefined !== result) { // if result is undefined, we are at the first or last iteration.
if (result.length) {
for (var k = 0, max = result.length; k < max; k++) {
console.log(result[k].name); // print name
// ... do something with the document here...
}
} else { // no more documents, end of the iteration
return; // implicitely returns undefined
}
}
// returns CHUNK_SIZE documents, starting from the j-th document
return collection.find({}, { limit: CHUNK_SIZE, skip: j, sort: { name: 1 }});
};
};
var funcs = [];
for (var i = CHUNK_SIZE; i <= LIMIT; i += CHUNK_SIZE) {
funcs.push(promiseFactory(i));
}
var loop = Q.fcall(promiseFactory(0));
funcs.forEach(function (f) {
loop = loop.then(f);
});
该脚本运行良好,确实实现了它的设计目的。
不过,我想改进一下:
- 我正在对集合中的文档数量进行硬编码 (
LIMIT
)。我想摆脱这个变量,让脚本检测何时停止。
- 我感觉这种方法可能不是最节省内存的方法。在我的代码中,
funcs.forEach()
一次链接了同一函数的许多副本(准确地说是 LIMIT/CHUNK_SIZE
副本)。由于我正在处理一个非常大的集合,我想知道是否有一种方法可以仅在仍有文档的情况下链接一个新函数,同时 运行 浏览整个集合。
我想我找到了解决这两个问题的办法。这只是我在下面突出显示的 promiseFactory()
中的一个简单添加。在这里添加它希望它对某人有用:
var promiseFactory = function (j) {
return function (result) {
if (undefined !== result) { // if result is undefined, we are at the first or last iteration.
if (result.length) {
for (var k = 0, max = result.length; k < max; k++) {
console.log(result[k].en + ' - ' + result[k].le);
}
} else { // no more entries, end of the iteration
return; // implicitely returns undefined
}
}
///////////////// CHANGE HERE ////////////////////////
return entries.find({}, { limit: CHUNK_SIZE, skip: j, sort: { en: 1 }}).then(promiseFactory(j + CHUNK_SIZE));
///////////////////// END ////////////////////////////
};
};
我在 Node 中编写了一个脚本,用于迭代大型 MongoDB 集合,一次返回一定数量的文档。
集合的格式很简单:
{
name: 'One',
data: '...'
},
{
name: 'Two',
data: '...'
},
...
我正在使用 Q 库完成这项工作,使用一系列承诺 运行 一个接一个:
'use strict';
var Q = require('q');
var monk = require('monk');
var CHUNK_SIZE = 100;
var LIMIT = 1000;
var collection = monk('localhost/dictionary').get('entries');
var promiseFactory = function (j) {
return function (result) {
if (undefined !== result) { // if result is undefined, we are at the first or last iteration.
if (result.length) {
for (var k = 0, max = result.length; k < max; k++) {
console.log(result[k].name); // print name
// ... do something with the document here...
}
} else { // no more documents, end of the iteration
return; // implicitely returns undefined
}
}
// returns CHUNK_SIZE documents, starting from the j-th document
return collection.find({}, { limit: CHUNK_SIZE, skip: j, sort: { name: 1 }});
};
};
var funcs = [];
for (var i = CHUNK_SIZE; i <= LIMIT; i += CHUNK_SIZE) {
funcs.push(promiseFactory(i));
}
var loop = Q.fcall(promiseFactory(0));
funcs.forEach(function (f) {
loop = loop.then(f);
});
该脚本运行良好,确实实现了它的设计目的。
不过,我想改进一下:
- 我正在对集合中的文档数量进行硬编码 (
LIMIT
)。我想摆脱这个变量,让脚本检测何时停止。 - 我感觉这种方法可能不是最节省内存的方法。在我的代码中,
funcs.forEach()
一次链接了同一函数的许多副本(准确地说是LIMIT/CHUNK_SIZE
副本)。由于我正在处理一个非常大的集合,我想知道是否有一种方法可以仅在仍有文档的情况下链接一个新函数,同时 运行 浏览整个集合。
我想我找到了解决这两个问题的办法。这只是我在下面突出显示的 promiseFactory()
中的一个简单添加。在这里添加它希望它对某人有用:
var promiseFactory = function (j) {
return function (result) {
if (undefined !== result) { // if result is undefined, we are at the first or last iteration.
if (result.length) {
for (var k = 0, max = result.length; k < max; k++) {
console.log(result[k].en + ' - ' + result[k].le);
}
} else { // no more entries, end of the iteration
return; // implicitely returns undefined
}
}
///////////////// CHANGE HERE ////////////////////////
return entries.find({}, { limit: CHUNK_SIZE, skip: j, sort: { en: 1 }}).then(promiseFactory(j + CHUNK_SIZE));
///////////////////// END ////////////////////////////
};
};