'How to get data from one controller by calling it from another controllers in Express without circular dependencies?

I am building an API using express js. I have structured it so that each data model (e.g. user, organization, etc.) has their own modules as such:

  • router - validates and sanitizes the http request at a high level and routes accordingly
  • controller - includes some business logic and validation that may rely on data in the persistence later
  • db - takes parameters from the controller to make queries to the database
  • model - defines the properties returned when the endpoint(s) for that model are called and which properties may be included in a POST or PATCH.

In summary, the User model has a userRouter.js, userController.js, userDB.js, and userModel.js, while all other data models follow the same structure.

There are, of course, several cases where the models interact with each other. For example, a User can belong to one or more Organizations, and I want to show a list of those organizations in the returned user response.

For the sake of keeping the code as loosely coupled as possible with consistent responses, I would like to call the organizationController's getOrganizations function from the userController. Likewise I have a need to use a similar method in the organizationController to get a list of users that belong to a given organization.

In these cases, they are the functional equivalent of calling the GET endpoint for those models, but there are other scenarios where I need to return data I wouldn't necessarily want to expose to an API route, such as fetching a single value indicating the users role in an organization from the database.

I began by requiring the organizationController in the userController and vice-versa, but this created a circular dependency and the functions I was trying to access were coming back as undefined.

To solve this, I ultimately created a "helperController" that each and any controller can call to get a function from another controller:

function getOrganizations(params){
   return require('./organizationController').getOrganizations(params)
}

function getUserIDByEmail(email){
    return require('./userController').getUserIDByEmail(email);
}

module.exports = { 
    getOrganizations,
    getUserIDByEmail 
}

To avoid the circular dependencies, I wrap the require statements inside of the functions the respective controllers would call, so that way the userController is not ultimately requiring itself by calling the helperController.

This works, but it feels a little hacky and like a violation of the DRY principle. I have also read that controllers should not generally call each other, but I am not sure what the alternative here is to achieve this.

Is this a sound way to do this or is there a better way to achieve what I want to do?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source