Stack Exchange
node executes asynchronously
In my express app I am implementing ACL using node_acl
my acl.js looks like:
var mongoose = require('mongoose'),
node_acl = require('acl'),
acl;

mongoose.connect('mongodb://127.0.0.1:27017/aclExample', function _mongo_connected(){
    var mongoBackend = new node_acl.mongodbBackend(mongoose.connection.db, 'acl_');
    acl = new node_acl(mongoBackend);

    
    console.log("ACL: ",acl);
});
set_roles();


function set_roles() {
    //set permissions for roles
    acl.allow([
        {
            roles: 'a',  //roles
            allows: [
                {resources: '/fe', permissions: ['put', 'delete']},
            ]   //permissions
        },
        {
            roles: 'b',
            allows: [
                {resources: '/fe/api', permissions: 'post'}
            ]
        },
        {
            roles: 'c',
            allows: [
                {resources: '/', permissions: ['post', 'put']}
            ]
        },
        {
            roles: 'd',
            allows: [
                {resources:'/fe', permissions: ['get', 'post']}
            ]
        }
    ]);
    acl.addUserRoles(420, 'b').then( ()=> console.log('added user'))
    .catch(err => console.error(err));
  
    acl.addUserRoles(520, 'a').then( ()=> console.log('added user'))
    .catch(err => console.error(err));
  
    //acl.isAllowed(userId, reso, pem);
  }

module.exports = acl;

and my app.js:
var acl = require('@root/fe-server/middlewares/fe.middleware.acl.js');
var express = require('express');
var app = express();
console.log("ACL: ",acl);

The output I get looks like this:
ACL:  undefined
added user
added user

I can understand that node executes the console statement in app.js before the connection is established and db is created but I can't seem to figure out how to fix this.
Any help will be much appreciated.

As you said yourself, mongoose.connect takes some time and therefore it accepts a callback function to be executed once it's finished, which you have been using already.
Within that callback function you create the acl ressource and that means anything using the acl variable also has to be executed from within that callback (either directly or indirectly). So in your case you would have to do something like this:
acl.js
const mongoose = require('mongoose');
const node_acl = require('acl');

const connect = (callback) => {
  mongoose.connect('mongodb://127.0.0.1:27017/aclExample', (err) => {
    if (err) return callback(err);

    const mongoBackend = new node_acl.mongodbBackend(mongoose.connection.db, 'acl_');
    const acl = new node_acl(mongoBackend);

    set_roles(acl).then(() => callback(null, acl)).catch(callback);
  });
};

const set_roles = (acl) => {
  acl.allow([ /* stuff */ ]);

  return Promise.all([
    acl.addUserRoles(420, 'b').then(() => console.log('added user b')),
    acl.addUserRoles(520, 'a').then(() => console.log('added user a')),
  ])
};

module.exports = connect;

main.js:
var connectACL = require('acl.js');
var express = require('express');
var app = express();

connectACL((err, acl) => {
  console.log('ACL: ', acl);
});

The important change is that require('acl.js') now returns a function which accepts a callback, so that you can safely use acl after it has been created.
You can also see that acl uses a different kind of handling asynchronicity, which is called "Promises" (the .then and .catch stuff). Both are valid options but you'll usually want to decide to use one only and convert the other one as soon as possible (like I do here with .then(() => callback(null, acl)).catch(callback)).
However you will need one of those whenever you deal with asynchronous functions, as you have ensure that your code is executed in the correct order.

Thank you for the response. You're making a lot of sense but this didn't solve the problem. It still logs ACL as undefined in my console. You think async await could be the solution?

async/await is just a different syntax for working with Promises.
In my example I didn't include much error handling for simplicity, but it's quite possible that something within connectACL failed. In callback style, you'll get any possible errors as first callback parameter, for promises there is the .catch function.
I also just added a parameter to set_roles to fix a TypeError.

Even if this works, I still won't be able to access acl methods in my routes folder for authorization such as acl.isAllowed() or acl.middleware(). This was the reason I was exporting the acl variable from my acl.js file.

That is a very common problem and there are various solutions based what framework you are using. In express you can build a middleware that adds req.acl = acl which will make it accessible in any subsequent handler.
Or as a more advanced solution you can return a getACL function from acl.js which returns a Promise that resolves to acl. It's implementation can then make sure that the actual connection stuff is only done once and the results cached and returned on subsequent calls.
