promised-mongo:无法最终确定 promise

promised-mongo: can't finalize promise

这是我正在处理的一段代码:它将 reddit 帖子保存到 mongoDB 集合。

我正在使用 promised-mongo

问题是当 for 循环完成并且所有数据都保存到数据库时,程序不会退出,它继续执行什么都不做,尽管在每个 promised-[=22 的末尾调用 done() =] 承诺链。

    for (var i = 0; i< posts.length; i++) { 
        posts[i].done = false;
        DB.posts.findOne({
            "id" : posts[i].id // it's 'id', not mongo's '_id'
        })
        .then(function(i) {
            return function(doc){
                if(doc) {
                    console.log('skipping')
                } else {
                    DB.posts.insert(posts[i]).then(function() {
                        console.log(arguments);
                        nSaved++;
                    });
                }
            }
        }(i))
        .catch(function(){
            console.log(arguments)
        })
        .done();
    }

我做错了什么?

这里有几个问题:

  • 您正在 for 循环中创建多个承诺,但没有跟踪它们
  • 您有一个 DB.posts.insert 创建承诺,但您没有等待它

以相反的顺序解决它们:

如果您不return DB.posts.insert 创建的承诺,则在完成之前将无法等待它。你需要return它:

return function(doc){
    if(doc) {
        console.log('skipping')
    } else {
        // here
        return DB.posts.insert(posts[i]).then(function() {
            console.log(arguments);
            nSaved++;
        });
    }
}

并且您还需要跟踪您正在创建的所有承诺,以便您知道它们何时全部完成。一种简单的方法是使用 .map() 将它们映射到一组承诺,然后使用 Promise.all() 等待它们。

假设posts是一个数组:

function ensurePost(post) {
    post.done = false;

    return DB.posts.findOne({
        "id" : post.id // it's 'id', not mongo's '_id'
    })
    .then(function(doc){
        if(doc) {
            console.log('skipping ' + post.id)
        } else {
            return DB.posts.insert(post).then(function() {
                console.log(arguments);
                nSaved++;
            });
        }
    })
    .catch(function(error){
        console.error('Error inserting', post.id, error);
    });
}

Promise.all(posts.map(ensurePost))
.done(function () {
    // all done. close the connection
});

这也消除了您在那里遇到的令人不快的 IIFE 的需要。