Controllers
Introduction
In EJS, a controller is a class responsible for providing action methods to execute specific functionality within a module.
Acting as an interface to a module, controllers provide predefined functionality which may be called from the application.
Controller classes
A controller is a class that resides in a module's Controller
namespace and has its name suffixed with Controller. Each controller class may optionally include a constructor which will be passed the active module instance and the application's file loader.
In many cases, a module only needs a single controller. However, for larger modules, it is a good idea to group related functionality into multiple controllers.
Enforcing suffixes on class and method names helps to protect against routing to non-controller classes or methods, inadvertently or otherwise.
Action methods
An action method is a method on a controller class with its name suffixed with Action. The application will call these methods to interact with modules from the outside. This ensures that a module can properly dictate how it should be used while preventing coupling to the application itself.
Action methods may optionally return a value. If the returned value is a component, it will be inserted into the active layout.
Asynchronous action methods
An asynchronous action method is a method that may not return immediately as it needs to wait for its processing to complete (e.g. waiting for a component to load). Instead of returning a value directly, asynchronous action methods return a Promise that will resolve to the return value.
Example: Loading resources just-in-time
Synchronous action methods
A synchronous action method is a method that does not contain any asynchronous processing, and optionally returns a value immediately.
Synchronous action methods are most useful for preloading related resources.
Always prefer asynchronous action methods.
Example: Preloading resources
In this example, MyComponent
and its dependencies will be loaded recursively when MyFirstController
is loaded. When mySyncMethodAction
is called, it can return MyComponent immediately as it is already loaded.
Preloading resources should be used sparingly and primarily for optimization when necessary. Excessive preloading can cause performance issues resulting from network or memory limits.
Using an abstract controller
When designing your controllers, it's likely you'll want to share some common functionality across many or all of them.
EJS provides a simple abstract controller with some convenience methods:
ElentraJS/Controller/ControllerAbstract#respond(componentName)
Accepts the filename of a component, relative to the module'sComponent
namespace. Returns a Promise that will resolve to the component when it is loaded.
If you extend the EJS ControllerAbstract
class instead of using it directly, you can limit coupling to a single point in your module or application.
Example: Use an abstract controller via composition
Example: Use an abstract controller via inheritance
Always prefer composition over inheritance as it removes the vertical coupling across classes, enhances flexibility, and simplifies maintenance.
Last updated