简体   繁体   中英

The array gets cleared after mongoose.findOne()

I am trying to get documents out of the database (questions) and store them in an array for further use (The questions would be asked to the players).

However, when I call findOne(), and add it's result to an array, the array is empty after the callback.. Even though it contains the data in there!

private Questions: iGeneralQuestion[];    

private LoadQuestions(): iGeneralQuestion[] {
        const result: iGeneralQuestion[] = [];
        for (let qid of this.GeneralArguments.questionIds) {
          QuestionModel.findOne({ id: qid }, (err: any, question: any) => {
            if (err) return err;
            if (!question) return question;
            this.Questions.push({
              questionId: question.id,
              question: question.question,
              answer: question.answer,
              otherOptions: question.otherOptions,
              timeLimit: question.timeLimit,
              difficulty: question.difficulty
              //explanation: question.explanation
              //pictureId: question.pictureId
            });
            console.log(this.Questions); //The array is full here! (Gets filled with each iteration)
          });
        }
        console.log(this.Questions); //But it doesn't contain anything here!
        return result;
      } 

This is the code that loads the documents, and saves their content in the array.

I have tried using the promise functions and find() instead of findOne().. To no avail!

I'm absolutely lost with this, as it shouldn't be about some kind of scope error. The Questions array is a field variable, but it seems to get cleared in the end.

Any help is appreciated!

When you call QuestionModel.findOne({ id: qid }, (err: any, question: any) => {...}); , you're registering a callback function that will be invoked after the document is found. But in the meantime (while findOne(...) looks for the document) the rest of the code continues to execute.

So after you've called QuestionModel.findOne(...) , the for loop continues. You haven't found a document yet - that's happening in the background. Eventually the for loop will complete and the last console.log(this.Questions) on the page is called followed by return result; . But, findOne(...) is still looking for documents in the background. It hasn't found anything yet, so console.log(this.Questions) doesn't display anything. The array is still empty at this point in time. Awhile later, after findOne(...) finally finds a document, then the callback is called.

It may be worth looking into promises when dealing with asynchronous code like this:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

More optimize way(reduce DB operations) instead of finding each record, find all recode in one shot than creating the result. Hope this helps :)

private LoadQuestions(cb){
    const result: iGeneralQuestion[] = [];
    QuestionModel.find({
        id: {
            $in: this.GeneralArguments.questionIds // Array of all ids
        }}, (err: any, questions: any) => {
                if (err) cb(err);
                questions.forEach((question) => {
                    if (question) {
                        result.push({
                            questionId: question.id,
                            question: question.question,
                            answer: question.answer,
                            otherOptions: question.otherOptions,
                            timeLimit: question.timeLimit,
                            difficulty: question.difficulty
                            //explanation: question.explanation
                            //pictureId: question.pictureId
                        });
                    }
                });
        return cb(null,result);
    });
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM