A flyweight dependency injection container for Node.js and the browser.
var di = new Dijs();
di.bind('config', function (app, done) {
fs.readFile(__dirname + "/../config.json", function (err, data) {
if (err) return done(err);
done(null, JSON.parse(data.toString()));
});
});
// Bind 'database' in the container, depending on 'config'
di.bind('database', ['config'], function (app, done) {
DBManager.connect(config, function (err, connection) {
done(err, connection);
});
});
/**
* GET /users
*/
exports.index = function (di, req, res, next) {
di.get('database', function (err, database) {
if (err) throw err;
database.query('users', function (err, users) {
if (err) throw err;
res.json(users);
});
});
};
var di = new Dijs();
di.bind('session.token', ['user'], function (app, done) {
var data = {
username: user.username,
password: user.password
};
jQuery.post('/api/sessions/new', data, function (response) {
return done(null, response.token);
});
});
jQuery('#login-form').on('submit', function () {
var user = {
username: $('#username').val(),
password: $('#password').val()
};
di.bind('user', function (app, done) { done(null, user); });
di.get('session.token', function (err, token) {
if (err) throw err;
// do something fun and exciting with token here!
});
});
Constructor method. Declares a new dijs container.
Bind a new value into the container. This value will be accessible with
the passed key after this point. The factory
function will not be
evaluated lazily, and no code will be run until necessary.
By default, factories are considered "shared," meaning that after the
first time the object is built, that same object will be reused for all
subsequent get
calls. You can disable this, forcing the container to evaluate
the factory upon each request by passing false
after the factory
function.
If the factory that you're defining has dependencies, you can supply them when binding. They will automatically be appended, in order, to the factory callback
The signature of the factory
callback is: container, callback
, where
container is the originating container, and a callback accepting an
optional error
and the instantiated value:
// Simple example
di.bind('fooer', function (container, done) {
var fooer = new Fooer();
if (fooer.hasError()) {
return done(fooer.getError());
}
done(null, fooer);
});
// Dependencies example
di.bind('secret_value', function (container, done) {
// Do something super complex here
done(null, 'shhh! secrets');
});
di.bind('bazzer', ['secret_value'], function (container, done, secret) {
var bazzer = new Bazzer(secret);
bazzer.on('connected', function () {
done(null, bazzer);
});
});
Retrieve the value(s) previously specified by key
(or keys
) from the
container. If multiple values are specified, they will be returned in
the order they were requested. Duplicate key requests are permitted:
di.get(['foo', 'bar', 'baz'], function (err, foo, bar, baz) {
document.getElementById('bazholder').innerHtml = foo + bar + baz;
});
di.bind('random', function (app, done) {
done(null, Math.random());
}, false); // Not a shared factory -- evaluated each request
di.get(['random', 'random', 'random'], function (err, rand1, rand2, rand3) {
process.stdout.write(
"For your enjoyment, 3 different random numbers:\n" +
[rand1,rand2,rand3].join(', ')
);
});
Effectively the same as di.get
, getOne
only accepts a singular
argument. There's probably no reason for you to use it.
MIT. See the LICENSE file for details.