5

I'm having trouble getting mongodb data into nodejs array as follow:

Test db:

{
  "supportTicket" : "viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf",
  "msgId" : 1379304604708.0,
  "username" : "Guest-OSsL2R",
  "message" : "hello",
  "_id" : ObjectId("5236849c3651b78416000001")
}

Nodejs:

function _getMsg(st, callback) {
    db.test.find({ supportTicket: st }).toArray(function (err, docs) {
        callback(docs);
    });
}

var nodeArr = _getMsg('viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf', function (res) {
    console.log(res); // --> res contain data and printed ok
    return res; 
});

console.log('return data: ' + nodeArr )  // --> However, nodeArr  is undefined.

And here is the result:

return data: undefined
return data: undefined
[ { supportTicket: 'viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf',
    msgId: 1379304604708,
    username: 'Guest-OSsL2R',
    message: 'dhfksjdhfkj',
    _id: 5236849c3651b78416000001 } ]
[ { supportTicket: 'viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf',
    msgId: 1379304604708,
    username: 'Guest-OSsL2R',
    message: 'dhfksjdhfkj',
    _id: 5236849c3651b78416000001 } ]

The question is: How can I get data from test db and assign the data to nodeArr?

4

4 回答 4

5

正如您所注意到的,控制台确实显示了_getMsg调用的结果。

_getMsg不返回值,因此当您尝试将nodeArr变量分配给结果时,它会获取 的值,undefined因为没有return值。即使您将其更改为返回值,在调用函数时,结果也没有返回。

find与许多 NodeJs 和 MongoDb 驱动程序一样,调用是异步的。因此,它不会立即返回,这就是为什么您需要回调在函数完成时发出信号的原因。如果没有这种模式,函数调用者将永远不会收到结果。

您在定义的回调内部有一个 return: return res。这会将结果返回给发起调用的函数:callback(docs)。虽然从技术上讲它没有任何问题,但没有理由这样做,因为调用者已经有了结果。这只是忙碌的工作。

此外,我会小心在 NodeJS 的全局范围内声明变量。对于异步行为(并且只有一个线程完成所有连接的所有工作),您可能会发现在任何给定时刻如果不检查就很难确定全局变量的值。

function _getMsg(st, callback) {
    db.test.find({ supportTicket: st }).toArray(function (err, docs) {
        callback(docs);
    });
}

_getMsg('viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf', function (res) {
    console.log(res); // --> res contain data and printed ok
    var nodeArr = res;  // just moved the nodeArr declaration to function scope
    // *** do next step here, like send results to client
});

如果您将结果发送回客户端,在对_getMsg您的调用内部可能会有类似这样的内容(假设它是在处理 http 的上下文中request):

response.writeHead(200, { 'Content-Type': 'application/json'});
response.write(JSON.stringify(nodeArr));
response.end();

可以包含在这样的基本内容中:

var http = require('http');
http.createServer(function (req, response) {
    // all requests return the results of calling _getMsg
    // this function won't return until the callback completes
    _getMsg('viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf', function (nodeArr) {        
        response.write(JSON.stringify(nodeArr));
        response.end();
    });
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
于 2013-09-16T11:15:44.690 回答
4

你可以这样做:

var nodeArr;
function _getMsg(st, callback) {
    db.test.find({ supportTicket: st }).toArray(function (err, docs) {
        callback(docs);
    });
}

_getMsg('viT8B4KsRI7cJF2P2TS7Pd0mfqaI5rtwf', function (res) {
    console.log(res); 
    nodeArr = res; 
});

console.log('return data: ' + nodeArr ) 

但通常这是一个糟糕的主意,在你的情况下,console.log它仍然会显示为undefined. 这是因为分配将在查询完成时完成,但节点仍将执行代码,直到发生这种情况。

通常你应该处理数据并在回调中做任何你想做的事情_getMsg。在大多数情况下,这是安全的工作方式。

于 2013-09-16T08:58:23.703 回答
1

您需要了解异步和同步流之间的概念。

db.test.find({ supportTicket: st }).toArray(function (err, docs) {
  if (err) throw err;
  nodeArr = docs;
});
于 2013-09-16T09:12:49.937 回答
0

logindata.find({ Name: req.body.username }).select().exec(function (err, data) { })

于 2020-07-26T16:04:19.620 回答