5

次のように、mongodb データを nodejs 配列に入れるのに問題があります。

テスト データベース:

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

Node.js:

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.

結果は次のとおりです。

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 } ]

問題は、テスト データベースからデータを取得し、そのデータを nodeArr に割り当てるにはどうすればよいかということです。

4

4 に答える 4

5

お気づきのとおり、コンソールには_getMsg呼び出しの結果が表示されました。

_getMsgは値を返さないため、nodeArr変数を結果に代入しようとすると、値がなかったため、値が取得undefinedされreturnます。値を返すように変更しても、関数の呼び出し時には結果が返されていません。

への呼び出しfindは、多くの NodeJ や MongoDb ドライバーと同様に非同期です。そのため、すぐには戻りません。そのため、関数が完了したときにコールバックを通知する必要があります。そのパターンがないと、関数の呼び出し元が結果を受け取ることはありません。

定義されたコールバック内に return があります: return res。これにより、呼び出しを開始した関数に結果が返されます: callback(docs). 技術的には問題はありませんが、呼び出し元が既に結果を取得しているため、実行する理由はありません。仕事が忙しいだけです。

さらに、NodeJS のグローバル スコープで変数を宣言する場合は注意が必要です。非同期動作 (およびすべての接続に対してすべての作業を行う 1 つのスレッドのみ) では、グローバル変数の値を検査せずに特定の時点で確認するのが難しい場合があります。

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 に答える