mongoose.findOne() 后数组被清除

Posted

技术标签:

【中文标题】mongoose.findOne() 后数组被清除【英文标题】:The array gets cleared after mongoose.findOne() 【发布时间】:2018-07-17 02:31:33 【问题描述】:

我正在尝试从数据库中取出文档(问题)并将它们存储在一个数组中以供进一步使用(问题将被询问给玩家)。

但是,当我调用 findOne() 并将其结果添加到数组时,回调后数组为空。即使它包含数据!

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;
       

这是加载文档并将其内容保存在数组中的代码。

我尝试过使用 promise 函数和 find() 而不是 findOne().. 无济于事!

我对此完全迷失了,因为它不应该是某种范围错误。 Questions 数组是一个字段变量,但它似乎最终被清除了。

感谢任何帮助!

【问题讨论】:

【参考方案1】:

当您调用QuestionModel.findOne( id: qid , (err: any, question: any) => ...); 时,您正在注册一个回调函数,该函数将在找到文档后调用。但与此同时(当findOne(...) 查找文档时)其余代码继续执行。

所以在您调用QuestionModel.findOne(...) 之后,for 循环将继续。您还没有找到文档 - 这是在后台发生的。最终 for 循环将完成,页面上的最后一个 console.log(this.Questions) 被调用,然后是 return result;。但是,findOne(...) 仍在后台寻找文档。它还没有找到任何东西,所以console.log(this.Questions) 没有显示任何东西。此时数组仍为空。过了一会儿,findOne(...) 终于找到了一个文档,然后调用回调。

在处理这样的异步代码时,可能值得研究一下 Promise:

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

【讨论】:

呃。我不知道我是怎么错过的!非常感谢您的帮助。我通过在类构造函数中调用 find() 来修复它,而不是将其作为参数传递给它,并使用 questionsLoaded bool 进行最终检查。【参考方案2】:

更多优化方式(减少数据库操作)而不是查找每条记录,一次找到所有重新编码而不是创建结果。希望这会有所帮助:)

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);
    );
 

【讨论】:

谢谢!是的,我当时使用了 find(),但我在构造函数本身中调用了它,而不是将它作为参数传递!

以上是关于mongoose.findOne() 后数组被清除的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose `findOne` 操作在 10000 毫秒后超时

Mongoose - FindOne 和 Search inside 和 Array

由于 Mongoose findOne 中的值错误,转换为 ObjectId 失败

Mongoose findOne as : Array = [FindOne , FindOne, FindOne ,FindOne, FindOne...] ,使用 ExpressJs

承诺问题:使用 Q.nfcall() 调用 mongoose.findOne()

如何使用mongoose findOne