变量工作但在代码块下面未定义

时间:2015-01-08 11:25:57

标签: javascript node.js mongodb

我有一个将(冻结)JSON对象插入MongoDB的函数:

var result = null, OID = null ; 
...

var test = dbHandle.collection('TestItems') ;
result = prepareObject() ;
test.insert(result, {w:1}, function(err, item) {
    if (err) throw err ; 
    OID = ObjectID(item[0]._id) ;
    test.update({_id: OID}, {$set: { userName: socket.userName, state: 'Ready'} }, {w:1}, function( err ) {
        if (err) throw err ;
        test.findOne({ _id: OID }, function (err, loaded) {
            if (err) throw err ;
            socket.emit('newData', { data: loaded }) ;
        });
    }) ;
}) ;

此代码可以正常运行。但是,在我的代码中,我需要使用OID和结果对象,但它们总是未定义的。我知道我一定做错了但我不知道是什么。我的背景是用C ++编写的,我的方法对我有意义,但这是我第一次尝试使用JavaScript / NodeJS / MongoDB。如果有人能指出我正确的方向,我将不胜感激。

例如,当我稍后尝试创建一个新对象时:

var myObj = {Title: result.Title, TID: OID, Stuff:'More Stuff Here'} ;

当将此对象插入MongoDB时,Title和TID值都未定义,但我的TestItems集合已正确更新,暗示OID具有值!这是某种形式的范围问题吗?我无法看到声明,作业和使用是如何在同一个闭包中。

1 个答案:

答案 0 :(得分:0)

这很可能是异步设计的问题。 你的test.insert函数获得了所谓的“回调”函数作为第三个参数。插入完成后将调用此函数,但test.insert不会阻止执行,因此您可以在调用回调之前执行更多代码。

为了让您更好地了解正在发生的事情,您的脚本按此顺序运行:

  • test.insert被称为
  • 调试test.insert之后的任何内容(你仍然没有OID和结果)
  • (稍后)调用test.insert的回调(设置了OID和结果属性)

您可以做的是将代码放在要使用OID和test.insert的函数中,并从test.insert回调中调用它:

result = prepareObject();
test.insert(result, ..., function(err, item) {
    // do stuff, get result objects, OID, etc
    // call your onInsertFinish function (pass result and OID to avoid using globals)
    onInsertFinish(result, OID);
});

function onInsertFinish(result, OID) {
    // do stuff with result and OID
}

希望这有帮助。