将mongodb数据获取到nodejs数组?

Đức*_*yễn 5 callback mongodb node.js mongojs

我在将mongodb数据放入nodejs数组时遇到问题,如下所示:

测试数据库:

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

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.
Run Code Online (Sandbox Code Playgroud)

结果如下:

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 } ]
Run Code Online (Sandbox Code Playgroud)

问题是:如何从测试数据库中获取数据并将数据分配给nodeArr?

dur*_*rum 5

你可以这样做:

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 ) 
Run Code Online (Sandbox Code Playgroud)

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

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


Wir*_*rie 5

如您所见,控制台确实显示了_getMsg调用结果。

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

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

你有回调的回报中定义: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
});
Run Code Online (Sandbox Code Playgroud)

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

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

可以将其包装成这样的基本内容:

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/');
Run Code Online (Sandbox Code Playgroud)