0

I am writing this code as a project for a customer and when i go to a show route i got this 500 internal server error

http.get('/files/:id', function(req, res) {
    var vid;
    var pap;
    Videos.find({}, function(err, videos) {
        if (err) {
            console.log(err);
        } else {
            vid = videos;
        }
    });

    Papers.find({}, function(err, file) {
        if (err) {
            console.log(err);
        } else {
            pap = file;
        }
    });

    Material.findById(req.params.id, function(err, found) {
        if (err) {
            console.log(err);
        } else {
            res.render('files', {
                file: pap,
                video: vid,
                current: found
            });
        }
    });
});

this is my show route code.

Note : if i reload the page the error is gone and the page open.

3
  • natural mistake who dive in JS world. keep in mind: everything that has to wait for third-party's response is done asynchronously. it can be db query request, some api request, something that watches for event and etc. (: Commented Jan 1, 2017 at 5:12
  • it just gone when i change the variables from local to global ! Commented Jan 1, 2017 at 13:21
  • For Your luck all responses from DB came in time))) Commented Jan 1, 2017 at 13:22

2 Answers 2

2

The reason is you need to wait for all the database queries to finish before rendering. In your code, it is possible for the page to render before the other two queries have completed and returned their data. The good news is that Mongoose supports Promises for asynchronous functions.

http.get('/files/:id', function(req, res) {
    Promise.all([
        Videos.find({}).exec(),
        Papers.find({}).exec(),
        Material.findById(req.params.id).exec()
    ]).then( ([video, paper, material]) => {
        res.render('files', {
            file: paper,
            video: video,
            current: material
        });
    }).catch( error => console.log(error) );
});
Sign up to request clarification or add additional context in comments.

Comments

1

The functions you're using with Mongoose are asynchronous in nature; the variables vid and pap are not initialized when you run res.render. When you attempt to use those variables in your frontend (template like Jade, Handlebars EJS, I don't know what you're using), they are undefined, and subsequently cause the 500 error. You'll need to run the functions such that the results of all Mongoose queries are available to res.render when it runs; either using an async NodeJS library, or calling each function within one another and then calling res.render at the end.

Solution 1: Using async Node module

var async = require('async');
async.parallel([
    // Each function in this array will execute in parallel
    // The callback function is executed once all functions in the array complete
    function (cb) {
        Videos.find({}, function(err, videos) {
            if (err) {
                return cb(err);
            } else {
                return cb(null, videos);
            }
        });
    },
    function (cb) {
        Papers.find({}, function(err, papers) {
            if (err) {
                return cb(err);
            } else {
                return cb(null, papers);
            }
        });
    },
    function (cb) {
        Material.findById(req.params.id, function(err, found) {
            if (err) {
                return cb(err);
            } else {
                return cb(null, found);
            }
        });
    }
], function (err, results) {
    if (err) {
        // If any function returns an error
        // (first argument), it will be here
        console.log(err);
    }
    else {
        // Even though the functions complete asynchronously,
        // the order in which they are declared in the array
        // will correspond to the position in the array
        // if it returns anything as a second argument.
        var videos = results[0];
        var files  = results[1];
        var found  = results[2];
        res.render('files', {
            file: files,
            video: videos,
            current: found
        });
    }
});

Solution 2: Nested Callbacks

Videos.find({}, function(err, videos) {
    var vid = videos;
    if (err) {
        console.log(err);
    } else {
        Papers.find({}, function(err, file) {
            var pap = file;
            if (err) {
                console.log(err);
            } else {
                Material.findById(req.params.id, function(err, found) {
                    if (err) {
                        console.log(err);
                    } else {
                        res.render('files', {
                            file: pap,
                            video: vid,
                            current: found
                        });
                    }
                });
            }
        });
    }
});

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.