2013-03-08 57 views
0

我会尝试尽可能简洁 - 猫鼬似乎不保存记录,直到整个脚本结束,即使在保存()部分异步调用:为什么Mongoose不能在脚本执行时保存记录?

var reallyBigData = require('./data.json'); 

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    newObj.x = data.x; 
    newObj.save(); 
}; 

this.on('importData', importData); 

for(var i in reallyBigData) { 
    this.emit('importData', reallyBigData[i]); 
}; 

这是一个粗略的简化,但你明白了。当我运行脚本并查询Mongo时,脚本运行时没有看到任何记录。如果我将数字限制为30,并将其导入快速结束,然后我会看到记录。

为什么Mongoose不在脚本执行时保存每条记录?

回答

2

问题是x.save()(或newObj.save())是异步的,你没有任何东西在等待它完成,而不是Node本身。

是异步的,它只有开始任务更新MongoDB中的集合并立即退出。它实际上不会“”直到后来,当一个可选的回调将被称为:

x.save(function (err, instance) { 
    // at this point, it either erred or saved 
}); 

但是,它有可能为x.save()近瞬间完成。时间结束的记录数量较少意味着你有一个竞争条件 - 这将首先完成:对MongoDB或Node/V8执行代码块的查询?

而且,使用EventEmitter,至少在这里采样的方式不足以使循环异步,因为您仍然同步地执行事件,并且emit()将同步循环处理任何处理程序。

但是,有许多“控制流程”库可用,可以帮助。这些措施包括promises实现,futures和迭代器一样async

var reallyBigData = require('./data.json'); 

async.each(Object.keys(reallyBigData), 
    function (key, callback) { 
     new Obj({ x: reallyBigData[key] }).save(callback); 
    }, 

    function (err, results) { 
     // called with an `err` or an `Array` of `results` (saved `Obj`s) 
    } 
); 
+0

有趣的是,我通过扔掉猫鼬并使用本地驱动程序解决了这个问题。我想知道Mongoose是否执行某种查询缓存。我会更多地尝试它,但似乎Mongoose在大循环结束之前没有处理任何插入请求。 – James 2013-03-11 17:05:48

+0

@James是的,Mongoose会排队查询,以便您可以*同步调用它们并让它们异步运行。这是“* callback hell *”的一种可能的解决方案。此外,本地驱动程序仍然是异步的,你仍然应该使用'insert()'和一个异步迭代器进行回调。 – 2013-03-11 17:20:16

0

首先,我认为你有一个讨厌的错误在这里:

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    Obj.x = data.x; 
    x.save(); 
}; 

原本应该最有可能读作:

var importData = function(data) { 
    var newObj = new Obj; // Mongoose Object 
    newObj.x = data.x; 
    newObj.save(); 
}; 

由于它看起来像是试图在您的模式上运行,而不是在模式中运行,而不是在模式中“新建”的模型。那有意义吗?或者,也许你就是这么想的,而你只是错过了打字?正如我没有看到你将如何从你有的代码中获得预期的结果,而不管它是如何执行到数据库的。也许正如你现在所做的那样,它很难发现模型已经改变了价值,或者它没有通过验证。

+0

你说得对。这是我的问题,而不是在代码中的拼写错误。不过谢谢。 – James 2013-03-11 17:03:49

相关问题