Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Create an object in a static function in Mongoose and handle its result from router

I am having trouble understanding the use of await in Node with mongoose and express.

Basically I have a page /profile where I generate a token for every get request I have, according to the user that is connected:

router.get('/profile', requiresLogin, (req, res, next) => {
    User.findById(req.session.userId).exec(function(err, user){
        if(err || !user){
            //Display error and return
            return res.send("Error");
        }

        var token = Token.generateToken(user);
        console.log("Token is: " + token);
        return res.send("Working");
    }
})

The function to generate the token is the following:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

TokenSchema.statics.generateToken = function(user){
    const newToken = new this({
        _userId: user._id,
        token: crypto.randomBytes(16).toString('hex')
    });
    await newToken.save();
    return newToken;
}

And I get an error on the await line saying: SyntaxError: await is only valid in async functions and the top level bodies of modules.

I think the code is quite intuitive, so what I want to accomplish is to have an static function to generate the Token objects. Then this function will return and other methods (like the one I posted that gets executed when getting /profile) can use it to create new tokens.

Is this the proper way to achieve what I am trying to achieve? I would like recommendations on how to do this code more "nodejs", since I am used to other languages where there are no promises and so on, and this is the best I could come up with. I know it is possible to do with callbacks and so on, but I think they might complicate the code for what it should be with other languages.

Thanks!

UPDATE: just after posting I saw that removing the await does what I expected, but as I have seen in here:

The save() method is asynchronous, so it returns a promise that you can await on.

So I don’t really understand how nor why it is working

>Solution :

You can’t use await in a non-async funciton, which means that:

  • generateToken must be async.
  • When calling generateToken in the request handler, you must also await that call.
  • Again, you can’t use await there without marking the anonymous handler function as async.

Your handler should look like this:

router.get("/profile", requiresLogin, (req, res, next) => {
    User.findById(req.session.userId).exec(async (err, user) => {
        if(err || !user) {
            return res.send("Error");
        }

        const token = await Token.generateToken(user);

        console.log("Token is: " + token);

        return res.send("Working");
    });
});

And the token generation function:

TokenSchema.statics.generateToken = async function(user) {
    const newToken = new this({
        _userId: user._id,
        token: crypto.randomBytes(16).toString('hex')
    });

    await newToken.save();

    return newToken;
}

You can also use async/await with Mongoose (instead of using callbacks), so your handler could look like this:

router.get("/profile", requiresLogin, async (req, res, next) => {
    try {
        const user = await User.findById(req.session.userId).exec();

        if (!user) return res.send("Can't find user.");

        const token = await Token.generateToken(user);

        console.log("Token is: " + token);

        return res.send("Working");       
    } catch (err) {
        return res.send("Error.");
    }
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading