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

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);
});

该脚本运行良好,确实实现了它的设计目的。

不过,我想改进一下:

我想我找到了解决这两个问题的办法。这只是我在下面突出显示的 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 ////////////////////////////

    };
};