0

This is a function to search test questions and match the answer given by the user and stored in the database. Console.log() displays all 6 questions but in random order. And the value of num is 6 for each iteration. if I do console.log(num) without finding anything from the database then I correctly display values 1,2,3,4,5,6.

function(req,res){
    var arr = [2,1,3,4,1,4],score=0, num=0;
    Test.find({name:req.params.testnum}).
    populate({
        path: 'question',
        model: 'Testques'
    }).
    exec(function(err,test){
        console.log(test)
        if(err){
            res.status(500).send('DB error');
        }
        else{
            arr.forEach(myFunction)
            function myFunction(value){
                num+=1;
                Testques.find({Serialnum:num},function(err,ques){
                    console.log(num);
                    if(err){
                        console.log(err);
                    }
                    else{
                        console.log(ques);
                        console.log(ques[0].answer);
                        if(ques[0].answer == value){
                            score=score+4;
                            console.log(score);
                        }
                    }
                })
            }
        }
    })
}
2
  • the error here seems to be that your function doesn't have a name... Commented Jul 12, 2018 at 20:43
  • 4
    The problem is that Testques.find is an asynchronous process, but forEach is not. So num+=1 will be executed all six times (once for each pass of the forEach) before any of your Testques.find queries have finished. So when they do finally finish, num is already at 6. Commented Jul 12, 2018 at 20:50

1 Answer 1

1

I agree with what CRice has to say about it. Inside the else of the callback, you're trying to run a synchronous forEach loop, but you're running an asynchronous block of code ( namely : Testques.find ) inside it, which would not work the way you wish it to work.

An elegant solution could be, to promisify your Mongoose calls, ( using promisifying utils available ), and then, once promisified, either use Promise.all to resolve the arrays of these queued up promises of Testques.find that you may push inside it.

Otherwise, you can also proceed as follows : Move your function inside the argument of the forEach to another method outside this method's scope, and then use basi knowledge of recursion to achieve what you wish to. It should resemble somewhat to this :

function cbIterator($index, arr, num, score) {
    if ($index < arr.length) {
        const value = arr[$index];
        num++;
        Testques.find({ Serialnum: num }, function (err, ques) {
            console.log(num);
            if (err) {
                console.log(err);
            }
            else {
                console.log(ques);
                console.log(ques[0].answer);
                if (ques[0].answer === value) {
                    score = score + 4;
                    console.log(score);
                }
                cbIterator($index + 1, arr, num, score);
            }
        });
    }
    return;
}

function myTestFunction(req, res) {
    // A bit of ES6. Feel free to replace the const / let with var if you are not comfortable with those
    const arr = [2, 1, 3, 4, 1, 4];
    let score = 0, num = 0;
    Test.find({ name: req.params.testnum })
        .populate({
            path: 'question',
            model: 'Testques'
        }).exec(function (error, test) {
            if (error) {
                res.status(500).send('DB Error');
            } else {
                let $index = 0;
                cbIterator($index, arr, num, score);
            }
        });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.