NodeJS回调范围

时间:2014-02-06 14:09:43

标签: javascript node.js mongodb mongoose

作为一名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的值将等于每个回调的数据数组中的最后一个元素。

我可以使用哪种模式来避免此问题?

感谢。

1 个答案:

答案 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(称为闭包)。