这是我正在处理的一段代码:它将reddit帖子保存到mongoDB集合中。
我正在使用promised-mongo库
问题是当for循环完成并且所有数据都保存到数据库时,程序不会退出,它会继续执行任何操作,尽管在每个promised-mongo promise链的末尾调用了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();
}
我做错了什么?
答案 0 :(得分:3)
这里有一些问题:
for
循环中创建多个承诺,但不跟踪它们DB.posts.insert
创造了一个承诺,但你没有等待它以相反的顺序解决它们:
如果你不回复DB.posts.insert
创建的承诺,那么在完成之前将无法等待它。你需要退货:
return function(doc){
if(doc) {
console.log('skipping')
} else {
// here
return DB.posts.insert(posts[i]).then(function() {
console.log(arguments);
nSaved++;
});
}
}
您还需要跟踪您正在创建的所有承诺,以便了解它们何时完成。一种简单的方法是使用.map()
将它们映射到promises数组,然后使用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的需要。