express-dinja
Use dependency injection pattern for Express 4.x applications. Inspired by express-di.
Usage
var express = ;var app = ;var inject = app; ; ; app; ;
On localhost:8080 you should see:
Why
Suppose you have this graph of middleware dependencies:
In express there is no built-in way to start execution of middlewares parallel, so you have two choices:
- Linearize middlewares tree and launch them one after one — and drop performance of app
- Write meta-middleware, that will launch independent middlewares side-by-side — and write boilerplate code
To reduce boilerplate code (you can see it in statusTodos function below) dependency injection pattern was added to express route function. Here is example how would applications look in plain express and with express-dinja:
Difference from express-di
This module is heavily based on code from express-di
, but has additional features, that I think is necessary for full dependency injection.
- Dependency resolving in injected dependencies
- No
express.Route.prototype
patching - No hardcoded cache
- No dependency inheritance in mounted apps (todo)
Benchmark
I used benchmark from express-di
to compare bare express application performance with patched version. Benchmark takes application with one middleware, that uses dependency injection and after middleware is done - sends 'Hello world' response.
Middleware is faked database connection, which will response in predefined time (horizontal bar) and requests/sec is the vertical bar:
API
dinja(app)
Returns Function
, that can inject dependencies into express application app
. It will patch route
method to enable injections in route-specific methods like use
, get
, post
and etc.
inject(name, fn)
Injects dependency with name name
and dependent express middlewares fn
.
fn
almost identically inherits express middleware signature: function([dependencies], req, res, next)
but with two differences:
- It can have own dependencies, that will be resolved, when this middleware is called.
next(err, value)
function accepts two arguments:err
andvalue
of dependency.
req
, res
and next
names are pre-defined to corresponding arguments of express middleware.
inject.resolve(name, callback)
Resolves dependency and calls callback:
{ var resolved = thisdependenciesname; if !resolved return ; return ;}
You can override it to add caching.
inject.declare(name, fn)
Stores dependency in inject.dependencies
object:
{ thisdependenciesname = fn;}
If you want to use shared singleton as storage, you can override this (do not forget to override inject.resolve
as well).
License
The MIT License (MIT) © Vsevolod Strukchinsky