bigbluebutton-Github/labs/bbb-html5-client/lib/modules.coffee
Leonardo Crauss Daronco f42eb27049 HTML5: moving global objects into modules
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.
2013-10-30 10:08:14 -02:00

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)