f42eb27049
There's a new class Module to organize modules in the application. Prevents errors from cyclic require's. The number of modules can still be reduced by organizing them better.
73 lines
2.5 KiB
CoffeeScript
73 lines
2.5 KiB
CoffeeScript
_ = require("lodash")
|
|
|
|
EventEmitter = require('events').EventEmitter
|
|
|
|
# Helper class to register and store modules.
|
|
# It stores a list of objects in an object literal indexed by the name of the module.
|
|
# Includes methods for a class to ask for a module and wait until it is ready.
|
|
#
|
|
# This class is used to prevent errors when modules are required in an order that
|
|
# would generate a circular dependency. In these cases, the objects might not be loaded
|
|
# entirely. See more at http://nodejs.org/api/modules.html#modules_cycles
|
|
# With this class, the class requiring a module can wait until the module is properly
|
|
# loaded. More than that, it will return an instanced object, not only a reference to
|
|
# a class (as usually done when using `require`).
|
|
#
|
|
# Example:
|
|
#
|
|
# ```
|
|
# modules = new Modules()
|
|
# modules.wait ["db"], ->
|
|
# # this callback will only be called when the module "db" is registered
|
|
# db = config.modules.get("db")
|
|
# ...
|
|
# # calls to register a module can be made anywhere in the application
|
|
# modules.register "db", new Database()
|
|
# ```
|
|
#
|
|
module.exports = class Modules extends EventEmitter
|
|
|
|
constructor: () ->
|
|
# the list of modules registered:
|
|
@modules = {}
|
|
# list of callbacks waiting for a module to be registered:
|
|
@callbacks = []
|
|
|
|
# Registers a new module with the name in `name` and the content in `object`.
|
|
# @param {string} name the name of the module
|
|
# @param {string} object the instance of the module
|
|
register: (name, object) ->
|
|
@modules[name] = object
|
|
@_checkCallbacks()
|
|
object
|
|
|
|
# Wait for a list of modules to be registered. `names` is an array of strings with
|
|
# the names of all modules that should be waited for. The callback in `callback` will
|
|
# only be called after *all* modules in `names` are registered.
|
|
wait: (names, callback) ->
|
|
@callbacks.push {modules: names, fn: callback}
|
|
@_checkCallbacks()
|
|
|
|
# Returns the module with the name in `name`.
|
|
get: (name) ->
|
|
@modules[name]
|
|
|
|
# Returns the list of all modules registered.
|
|
all: () ->
|
|
@modules
|
|
|
|
# Run through the list of registered callbacks in `@callbacks` to see if any of
|
|
# them are ready to be called (if all modules waited for are available).
|
|
_checkCallbacks: () ->
|
|
toRemove = []
|
|
for cb in @callbacks
|
|
done = true
|
|
for name in cb.modules
|
|
unless @modules[name]?
|
|
done = false
|
|
break
|
|
if done
|
|
cb.fn()
|
|
toRemove.push cb
|
|
@callbacks = _.filter(@callbacks, (i) -> i not in toRemove)
|