作为一名js / node新手,我在理解如何解决这个问题时遇到了一些问题。
基本上我有一个对象列表,如果它们尚不存在,我想保存到MongoDB数据库。
以下是一些代码:
var getDataHandler = function (err, resp, body) {
var data = JSON.parse(body);
for (var i=0; i < data.length; i++) {
var item = data[i];
models.Entry.findOne({id: item.id}, function(err, res) {
if (err) { }
else if (result === null) {
var entry = new models.Entry(item);
feedbackEntry.save(function(err, result) {
if (err) {}
});
}
});
}
}
我遇到的问题是因为它是异步的,一旦执行new models.Entry(item)
行,item的值将等于每个回调的数据数组中的最后一个元素。
我可以使用哪种模式来避免此问题?
感谢。
答案 0 :(得分:2)
有两种模式可供选择:
1)回调。那就是你通过将它们作为参数传递来继续调用函数中的函数。回调通常很好但是,尤其是服务器端在处理数据库或其他异步资源时,你快速结束“回调地狱”,你可能会厌倦寻找减少代码缩进级别的技巧。您有时可能想知道真正如何处理异常。但回调是基础:你必须了解如何使用回调处理该问题。
2) Promises。使用promises,你可能有类似的东西(例如来自我的related blog post):
db.on(userId) // get a connection from the pool
.then(db.getUser) // use it to issue an asynchronous query
.then(function(user){ // then, with the result of the query
ui.showUser(user); // do something
}).finally(db.off); // and return the connection to the pool
不是将下一个函数作为回调传递,而只是链接then
(事实上它有点复杂,你有其他函数,例如处理集合和并行解析或错误捕获在一个干净方式)。
关于调用回调之前变量演变的范围问题,标准解决方案是这样的:
for (var i=0; i<n; i++) {
(function(i){
// any function defined here (a callback) will use the value of i fixed when iterating
})(i);
});
这是有效的,因为调用一个函数会创建一个作用域,你在该作用域中创建的回调会保留一个指向该作用域的指针,它将获取i
(称为闭包)。