关于终止动态构造的承诺序列

时间:2015-11-16 20:10:57

标签: node.js promise q

我在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个副本)。由于我正在处理一个非常大的集合,我想知道是否有一种方法来链接一个新的功能,只有当还有文件时,在运行集合时。

1 个答案:

答案 0 :(得分:0)

我想我找到了解决这两个问题的方法。这只是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 ////////////////////////////

    };
};