async-ioc

IoC container with async support

Usage no npm install needed!

<script type="module">
  import asyncIoc from 'https://cdn.skypack.dev/async-ioc';
</script>

README

AsyncIoC for Node JS

Asyncronous IoC and dependency injection for Node JS.

Usage

First create a container:

var ioc = require('async-ioc').createContainer();

Then register services on that container:

ioc.register('service', someFunction);
ioc.register('anotherService', require('./anotherservice'));

You can specify dependencies for a service:

ioc.register('serviceThree', serviceThreeFactory, ['service', 'anotherService']);

Load an entire folder:

ioc.registerAll('/path/to/services');

...all registered services will be named by the file/folder unless the $implement attribute is set.

And start a service with dependency injection:

ioc.start('serviceThree');

You can also chain the methods:

require('async-ioc').createContainer()
    .register('service', someFunction)
    .register('anotherService', require('./anotherservice'))
    .register('serviceThree', serviceThreeFactory, ['service', 'anotherService'])
    .start('serviceThree')
    .then(function(serviceThree) {
        // do something with serviceThree
    });

Service Signature

The factory/function for the service should have the following signature:

var someService = function(services) {
    // ...
    // service initialization logic
    // ...

    return theService;
};

Typically you would expose this in a module:

module.exports = function(services) { };

... where services is an object containing the injected services

Attributes

$implement

Alias of $implements

$implements

Defines the service or interface name this module implements.

Type: String or Array[String]

Default: The file or folder name.

Notes: A module can implement multiple services or interfaces.

// implement a service or interface
module.exports = function(services) { };
module.exports.$implements = 'serviceName';
// implement multiple services or interfaces
module.exports = function(services) { };
module.exports.$implements = ['service1', 'service2'];

$inject

Defines the services to be injected for this service. These should be supplied as an array of string values containing the service names.

Default: No services ([])

module.exports = myService;
module.exports.$inject = ['dependencyOne', 'dependencyTwo'];

function myService(services) {
    services.dependencyOne.someMethod();
}

Asyncronous Services

Method 1: Promises

Simply return a promise from the service factory.

module.exports = myService;

function myService(services) {
    var deferred = Q.defer();

    // this service will finish loading in 1 second
    setTimeout(function() {
        deferred.resolve();
    },1000);

    return deferred.promise;
}

Method 2: start() method

Return an object that defines a .start() method that accepts a Node-style callback (ie: function(err)) to be called on completion. The start method will be called before injecting into the first service.

module.exports = myService;

function myService(services) {

    return {
        start: function(done) {

            // if an error occurs, call done() with the error
            if (someErrorOccurred) done(someErrorOccurred);

            // this service will finish loading in 1 second
            setTimeout(function() {
                done();
            },1000);
        }
    };

}

Shutdown / Stop process

TODO:

Method Summary

All container methods are chainable, except for get and start.

Still To Document

A lot to do!

  • debug
  • define
  • defineAll / defineFolder
  • get
  • logTo
  • recurseServices
  • recurseInterfaces
  • register
  • registerAll / registerFolder
  • reset
  • start
  • stopOn
  • stopTimeout