Home > Back-end >  Cannot use Async/Await in a Serverless NodeJS Function
Cannot use Async/Await in a Serverless NodeJS Function

Time:01-07

I'm new to Serverless with NodeJS, I'm trying to use an Async function to hash a password and perform some stuff in a database, the problem is that when I declare the functions async I always get this error:

enter image description here

But if I remove the async keyword here:

module.exports.login = async (event, context, callback) => {

the function runs properly, but of course I won't be able to use promises within the function.

This is an endpoint, to make API calls.

Here's my code:

'use strict';

require('dotenv').config({ path: './.env' });

const dataBase = require('./utils/db');
const bcrypt = require('bcrypt');

const encryptPassword = async (plainPassword) => {
   const saltRounds = 10;
   const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
   return hashedPassword;
};

module.exports.login = async (event, context, callback) => {
   context.callbackWaitsForEmptyEventLoop = false;
   const parsedBody = JSON.parse(event.body);
   const connect = dataBase.connectToDatabase();
   const newPassword = await encryptPassword('test');

   console.log(newPassword);

   connect.query('SELECT * FROM users', (error, results, fields) => {
      if (error) {
         console.error(error);
         callback(null, {
            statusCode: 500,
            body: JSON.stringify({
               error: JSON.stringify(error),
               message: 'Internal Server Error Booh!',
            }),
         });
      }
      if (results) {
         callback(null, {
            statusCode: 200,
            body: JSON.stringify({
               error: results,
               message: 'No Error',
            }),
         });
      }
   });
};

Here my db connection and config:

db.js

const mysql = require('mysql');
const isDev = true;

// Create mySQL Connection
const connectToDatabase = () => {
   const pool = mysql.createPool({
      host: isDev ? process.env.DATABASE_HOST_DEV : process.env.DATABASE_HOST_PROD,
      user: isDev ? process.env.DATABASE_USER_DEV : DATABASE_USER_PROD,
      password: isDev ? process.env.DATABASE_PASSWORD_DEV : DATABASE_PASSWORD_PROD,
      database: isDev ? process.env.DATABASE_DATABASE_DEV : DATABASE_DATABASE_PROD,
      multipleStatements: true,
   });
   return pool;
};

exports.connectToDatabase = connectToDatabase;
exports.mysql = mysql;

What am I missing?

EDIT:

The purpose of all this, it's because I'm learning serverless.

All this will end up in an AWS Lambda with an endpoint using API Gateway.

So, when you call this endpoint, you will be sending some params to register/login into an app.

I need to use async/await because if you register an account, the password needs to be hashed and then store into a database or if you login, the password will need to be compared, both of these actions are asynchronous ones.

That's why I need the endpoint to be an async function.

EDIT 2:

Reading this post: https://github.com/netlify/netlify-dev-plugin/issues/160

As Phil mention, async and callback shouldn't be used togehter, so I modified my code like this, and same error:

'use strict';

require('dotenv').config({ path: './.env' });

const dataBase = require('./utils/db');
const bcrypt = require('bcrypt');

const encryptPassword = async (plainPassword) => {
   const saltRounds = 10;
   const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
   return hashedPassword;
};

module.exports.login = async (event, context, callback) => {
   context.callbackWaitsForEmptyEventLoop = false;
   const parsedBody = JSON.parse(event.body);
   const connect = dataBase.connectToDatabase();
   const newPassword = await encryptPassword('test');

   console.log(newPassword);

   connect.query('SELECT * FROM users', (error, results, fields) => {
      if (error) {
         console.error(error);
         return {
            error: 'some error to test',
         };
      }
      if (results) {
         return {
            body: 'someBody',
         };
      }
   });
};

Regards.

CodePudding user response:

Taking a quick look at the docs, it doesn't look like you should be mixing async with the callback arg. Just use one or the other, not both.

You could migrate to the mysql2 library so you can use promises or stick with the one you've got and use encryptPassword("test").then() instead of await

// no async
module.exports.login = (event, context, callback) => {
  // remove this, you don't want it
  // context.callbackWaitsForEmptyEventLoop = false;

  const parsedBody = JSON.parse(event.body);
  const connect = dataBase.connectToDatabase();
  encryptPassword("test").then(newPassword => { // use .then()
    console.log(newPassword);

    // callback APIs are a pain, recommend migrating to mysql2 and use promises
    connect.query('SELECT * FROM users', (error, results, fields) => {
      if (error) {
        console.error(error);
        return callback(null, {
          statusCode: 500,
          body: JSON.stringify({
            error: JSON.stringify(error),
            message: 'Internal Server Error Booh!',
          }),
        });
      }
      callback(null, {
        statusCode: 200,
        body: JSON.stringify({
          error: results, // error?
          message: 'No Error',
        }),
      });
    }
  });
}
  •  Tags:  
  • Related