2013-09-23 3 views
2

나는 nodegs를 사용하여 Mongoose에서 Mongoose의 데이터를 쿼리합니다. 데이터를 얻은 후에 클라이언트에 응답하기 전에 데이터에 대해 작업을 수행해야합니다. 그러나 나는 반환 가치를 얻을 수 없다. Google에서 살펴본 후 Node.js 함수가 비동기 자바 스크립트 함수 (비 I/O 차단)임을 알게되었습니다. 나는이 혀를 (http://www.youtube.com/watch?v=xDW9bK-9pNY) 시도하지만 그것은 작동하지 않습니다. 아래는 제 코드입니다. myObject는 "find()"함수 내부에서 평가되고 "find()"함수 외부에서 정의되지 않습니다. 그렇다면 데이터를 얻으려면 어떻게해야합니까? 감사!Nodejs의 비동기 함수에서 반환 값

var Person = mongoose.model('Person', PersonSchema); 
var Product = mongoose.model('Product', ProductSchema); 
var myObject = new Object(); 

Person.find().exec(function (err, docs) { 
    for (var i=0;i<docs.length;i++) 
    { 
    Product.find({ user: docs[i]._id},function (err, pers) { 
    myObject[i] = pers; 
    console.log(myObject[i]); //return the value is ok 
    }); 
    console.log(myObject[i]); //return undefined value 
    } 
    console.log(myObject); //return undefined value 
}); 
    console.log(myObject); //return undefined value 

app.listen(3000); 
console.log('Listening on port 3000'); 
+0

이것은 내 github 게시물입니다 : https://github.com/LearnBoost/mongoose/issues/1706#issuecomment-24887415 –

답변

8

값이 정의되지 않은 이유는 찾기 기능이 비동기 적이므로 언제든지 완료 할 수 있기 때문입니다. 귀하의 경우에는 console.log()을 사용한 후에 끝나기 때문에 액세스 할 때 그 값은 정의되지 않습니다.

이 문제를 해결하려면 찾기 기능의 콜백 내에서만 값을 사용할 수 있습니다.

var Person = mongoose.model('Person', PersonSchema); 
var Product = mongoose.model('Product', ProductSchema); 
var myObject = new Object(); 

function getData(docs, callback) { 
    function loop(i) { 
    Product.find({ user: docs[i]._id}, function (err, pers) { 
     myObject[i] = pers; 

     if (i < docs.length) { 
     loop(i + 1); 
     } else { 
     callback(); 
     } 
    }); 
    }; 
    loop(0); 
}; 

Person.find().exec(function(err, docs) { 
    getData(docs, function() { 
    // myObject has been populated at this point 
    }); 
}); 

데이터 처리가 이전 반복이 완료 될 때까지 대기하는 루프로 이동되었습니다. 이 방법으로 래퍼 함수에서 콜백을 시작하기 위해 마지막 콜백이 시작된 시점을 결정할 수 있습니다.

+0

감사합니다 hexacyanide,하지만 작동하지 않습니다, 그것은 워드 프로세서 [i]의 속성을 읽을 수 없습니다. ._id –

2

console.log 기능이 실행될 때까지는 쿼리가 아직 완료되지 않았으므로 "정의되지 않음"이 표시됩니다. 이것이 바로 nodeJS의 비 동시성의 핵심입니다. 예를 들어

,

Person.find().exec(function (err, docs) { 
    for (var i=0;i<docs.length;i++) 
    { 
    Product.find({ user: docs[i]._id},function (err, pers) { 
    myObject[i] = pers; 
    console.log(myObject[i]); //return the value is ok 
    }); 
    console.log(myObject[i]); //return undefined value 
    } 
    console.log(myObject); //return undefined value 
}); 

console.log(myObject); // <-- Initially, this value will be undefined. After some miliseconds (Or the duration of the .exec function, myObject will contain the results. 

쿼리가이 값을 사용할 수 있도록, 내가 함수의 마지막 콜백으로 app.listen(3000);console.log('Listening on port 3000'); 이동 추천 할 것입니다 끝날 때까지 실제로 기다려야합니다.

this 노드 모듈도 확인하시기 바랍니다. 비동기/동기 함수를보다 쉽게 ​​빌드하고 모든 비동기 함수가 완료되면 콜백을 실행할 수 있습니다.

+0

내받은 편지함에서 "전역 범위 (Person.find(). exec() ... 바깥 쪽의 값을 설정/가져오고 싶지만 여기에서 볼 수 있습니다. 그렇지? –