2

I have the code below. I need to use the value of con in other functions but I have no possible solution for this. I tried using .thens and awaits like other stack articles but i kept getting the error that con is not valid.

I am truly stuck and unsure how to handle this.

service.js

async function connectToDatabase(secret) {
  
  try {
      const secretValue = await getSecretPromise(secret)

      const { host, port, username, password, dbname } = JSON.parse(secretValue);

      let con = mysql.createConnection({
          host: host,
          port: port,
          user: username,
          password: password,
          database: dbname
      });
      con.connect(function(err) {
        if (err) throw err;
        console.log("Connected to database!");
      });
      return con;
  } catch (error) {
      console.error(error)
  }
}

// Start an IIFE to use `await` at the top level
(async function(){
  let con = await connectToDatabase(secretName);
})();

function createUser({ data }) {
  return new Promise((resolve, reject) => {
    var sql = `query`;
    con.query(sql, function (err, result) {
      //does not work currently because ReferenceError: con is not defined
    });
  });
}

controller.js

async function getUsers(req, res, next) {

    service.getUsers().then(function(val) {
        res.json(val)
    });
}

getsecretpromise

function getSecretPromise(secretName) {
  return new Promise((resolve, reject) => {
    client.getSecretValue({SecretId: secretName}, function(err, data) 

    {
      //do stuff
    }
    }

enter image description here

service.getUsers

//this is in service.js
module.exports = {
  createUser,
  getUsers,
  patchUser,
  loginUser,
  updateCallForward,
  getEmail,
  getCallForwardingNumber,
  getDB
};

function getUsers() {
  return new Promise((resolve, reject) => {

    var sql = `sql`;

    getDB().then(con => {
      con.query(sql, function (err, result) {
        if (err) throw err;
        resolve(result);
      });
    });

  });
}
Juliette
  • 4,309
  • 2
  • 14
  • 31

3 Answers3

0

You are defining the con variable after it's being returned, your IIFE starts working once it is read. What I am trying to say is you need to move that function up and if thats not an option then you need to define con before returning it. If you alredy defined it before this function then I dont know.

async function connectToDatabase(secret) {
  
    // Start an IIFE to use `await` at the top level
    (async function(){
      let con = await connectToDatabase(secretName);
    })();

    try {
        const secretValue = await getSecretPromise(secret)

        const { host, port, username, password, dbname } = JSON.parse(secretValue);

        let con = mysql.createConnection({
            host: host,
            port: port,
            user: username,
            password: password,
            database: dbname
         });
         con.connect(function(err) {
             if (err) throw err;
             console.log("Connected to database!");
         });
         return con;
    } catch (error) {
          console.error(error)
    }
}

function createUser({ data }) {
    return new Promise((resolve, reject) => {
        var sql = `query`;
        con.query(sql, function (err, result) {
        //does not work currently because ReferenceError: con is not defined
    });
  });
}
SoloOrchid
  • 71
  • 4
0

You would ideally do something like this. This would hide your instance(not really for this case) from rest of the code as you will access it through a getter function. Of course you need to import your secret as a constant. It doesn't make sense to pass it as a parameter unless you have multiple dbs

let con = null;

async function connectToDatabase(secret) {

    try {
        const secretValue = await getSecretPromise(secret)

        const { host, port, username, password, dbname } = JSON.parse(secretValue);

        con = mysql.createConnection({
            host: host,
            port: port,
            user: username,
            password: password,
            database: dbname
        });
        con.connect(function (err) {
            if (err) throw err;
            console.log("Connected to database!");
        });
        return con;
    } catch (error) {
        console.error(error)
        con = null;
    }
}

export async function getDB() {
    if (con == null) {
        let secretObj = {};
        return await connectToDatabase(secretObj);
    }
    else {
        return Promise.resolve(con);
    }
}

export function createUser({ data }) {
    return new Promise((resolve, reject) => {
        var sql = `query`;
        getDB().then(con => {
            con.query(sql, function (err, result) {
                //does not work currently because ReferenceError: con is not defined
            });
        });
    });
}
Berkays
  • 364
  • 3
  • 10
0

The code can be simplified (and repaired) by making promise-returning versions of the mysql callback style functions...

async function connect(connection) {
   return new Promise((resolve, reject) => {
     connection.connect(function (err) {
       err ? reject(err) : resolve(connection)
     });
   })
}

async function query(connection, query) {
  return new Promise((resolve, reject) => {
   connection.query(query, function (err, results, fields) {
     err ? reject(err) : resolve({results, fields});
   });
 });
}

Only these functions should create new promises explicitly. This cleans up the connectToDatabase function...

async function connectToDatabase(secret) {
  try {
      const secretValue = await getSecretPromise(secret)
      const { host, port, username, password, dbname } = JSON.parse(secretValue);

      let con = mysql.createConnection({
          host: host,
          port: port,
          user: username,
          password: password,
          database: dbname
      });
      return await connect(con);
  } catch (error) {
      console.error(error)
  }
}

And it cleans up createUser substantially...

async function createUser({ data }) {
  try {
    const connection = await connectToDatabase(secretName);
    let {results, fields} = query(connection, 'query');
    // and so on
   
  } catch(error) {
    console.log(error);
  }
}

Not that getSecretPromise() might require the same treatment, but is not completely specified in the OP.

Other caveats: not tested (or even compiled). Relies on values in scope whose definitions are not shown in the OP (e.g. secretName).

danh
  • 62,181
  • 10
  • 95
  • 136