npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

servicelocatorjs

v1.0.5

Published

Dependency injection approach using Service Locator pattern

Downloads

95

Readme

Service Locator

Implementation of the dependency injection approach using the Service Locator pattern.

Service Locator is a dependency injection pattern. The Service Locator pattern does not describe how to instantiate the services. It describes a way to register services and locate them in a global point of access. A Service Locator should be able to locate a service using a central registry without knowing its concrete type. For example, it might use a string key which on request returns the object depending on code initialization. This allows you to replace the concrete implementation of the dependency without modifying the objects.

Advantages:

  • option of adding extra attributes and methods using mixin pattern to all objects registered in Service Locator;
  • option of lazy instantiation;
  • un-registering instances;
  • un-registering objects;
  • applications can optimize themselves at run-time by selectively adding and removing items from the Service Locator;
  • large sections of a library or an application can be completely separated; the only link between them becomes the registry;
  • it solves the drawback of factories, allowing to manage the creation of objects automatically and centrally.

Drawbacks:

  • your classes have an extra dependency on Service Locator;
  • you have to write additional code to add service references to the locator before your service objects use it;
  • objects placed in the registry are black boxed, this makes it harder to detect and recover from their errors, and may make the system as a whole less reliable;
  • sometimes registry can be a security vulnerability, because it allows outsiders to inject code into the application;
  • the source code has added complexity, this makes the source code more difficult to comprehend;
  • registry hides the object dependencies, causing errors when dependencies are missing;
  • registry makes the code harder to test, since all tests need to interact with the same global Service Locator; to set the fake dependencies of a service object under test.

API

Require in Node

var ServiceLocator = require("servicelocatorjs");
printLog (flag?: boolean)

Takes true/false values as a parameter. When true, writes information about events and channels into the console.

ServiceLocator.printLog(true);
setMixin (objectWithMixins: Object)

Takes an object as a parameter. The object contains a set of additional properties and/or methods, which have to contain all objects registered in Service Locator.

ServiceLocator.setMixin({
	mixinMethod: function () {}
});
getMixin (): Object

Return current set mixins.

ServiceLocator.getMixin();
mixin(objectWithMixins?: Object): Object

Set and/or return mixins.

ServiceLocator.mixin({
	mixinMethod: function () {}
});
register (serviceName: String, serviceObject: Function|Object, instantiate?: boolean, constructorArguments?: Array): boolean

Registers an object serviceObject under the name serviceName. The flag instantiate shows whether lazy instantiation is required to request the object from Service Locator. By default instantiate is true.

ServiceLocator.register('serviceName', function (a, b) {
	this.a = a;
	this.b = b;
}, true, [1, 2]);
ServiceLocator.register('serviceName', {
	a: 1,
	b: 2
});
registerAll (arrayOfServices: Array): Array

Calls the register function for each element of arrayOfServices. Each element of the array must contain one of the ID or id properties for defining the object name, and service/object/creator for defining the object under registration. There is optional instantiate.

ServiceLocator.registerAll([
	{
		/**
		 * @constructor
		 * @param {*} value
		 */
		creator: function (value) {
			this.prop = value;
		},
		id: 'ServiceFive',
		instantiate: false
	},
	{
		service: {
			prop: 'Some property'
		},
		id: 'ServiceSix'
	}
]);
get (serviceName: String): null|Object

Returns the instance of a registered object with an indicated serviceName or creates a new one in case of lazy instantiation.

ServiceLocator.get('serviceName')
instantiate (serviceName: String): boolean

Instantiates service by name.

ServiceLocator.instantiate('serviceName')
instantiateAll (filter?: Function)

Instantiates and returns all registered objects. Can take the filter function as an argument. The filter function must return the logical value. In case filter is predefined, only the services that underwent the check will be instantiated.

ServiceLocator.instantiateAll(function (serviceName) {
	if (serviceName === 'ServiceName') {
		return false;
	} else {
		return true;
	}
})
getAllInstantiate (): Array

Returns the array of instantiated service objects.

ServiceLocator.getAllInstantiate();
isRegistered (serviceName: String): boolean

Checks whether the service is registered.

ServiceLocator.isRegistered('ServiceName');
isInstantiated (serviceName: String): boolean

Checks whether the service is instantiated.

ServiceLocator.isInstantiated('ServiceName');
removeInstance (serviceName: String): boolean

Deletes a service instance with an indicated serviceName. Returns false in case the service with the indicated serviceName is not found or has no instance. This does not remove the service itself, but only its instances.

ServiceLocator.removeInstance('ServiceName');
unRegister (serviceName: Array|String, removeMixins?: boolean): null|Object

Deletes a service named serviceName from Service Locator and returns its instance. The flag removeMixins points at the necessity to delete the added mixin properties.

ServiceLocator.unRegister('ServiceName', true);
unRegisterAll(removeMixins?: boolean): Object

Deletes all registered services from Service Locator and returns the array of their instances. The flag removeMixin points at the necessity to delete the added properties in the services that will be deleted.

ServiceLocator.unRegisterAll(true);

Example

###Creating a new instance:

####In runtime environment like node.js or io.js:

var ServiceLocator = require("servicelocatorjs");

####In the browser:

var ServiceLocator = window.ServiceLocator;

####Print debug information in console:

ServiceLocator.printLog(true);

####Create mixin for services:

var mixin = {
	/**
	 * Set in service object new property <_state> for further use
	 * @param {*} value
	 */
	setState: function (value) {
		this._state = value;
	},
	/**
	 * Get <_state> property from service object
	 * @return {*}
	 */
	getState: function () {
		return '_state' in this ? this._state : undefined;
	},
	/**
	 * Get service object name
	 * @return {String}
	 */
	getName: function () {
		return 'name' in this ? this.name : 'Service has no name!';
	}
};

####Set it for ServiceLocator:

ServiceLocator.setMixin(mixin);

####Create constructors for services:

/** @constructor */
function ServiceOne() {
	this.name = 'ServiceOne'; // This property is not required. Made for example
}

/** @constructor */
function ServiceTwo() {
	this.name = 'ServiceTwo';
	this.serviceFunction = function () {
		return 'Service number two function';
	};
}
/**
 * @param {*=} data
 * @constructor
 */
function ServiceThree(data) {
	// Service without <name> property
	this.data = data;
}
/** @constructor */
function ServiceFour() {
	this.name = 'ServiceFour';
}

####Registering service objects in "ServiceLocator"

####With instantiation immediately after registration:

ServiceLocator.register('ServiceOne', ServiceOne, true);

In Service Locator registry its instance looks like this:

{
	__mixins: ["id", "setState", "getState", "getName"]
	getName: function,
	getState: function,
	id: "ServiceOne",
	name: "ServiceOne",
	setState: function
}

####With lazy instantiation:

ServiceLocator.register('ServiceTwo', ServiceTwo, false);

No instance, but there is a construction function:

{
	creator: function ServiceTwo(),
	name: "ServiceTwo",
	prototype: ServiceTwo
}

####Default immediate registration:

ServiceLocator.register('ServiceThree', ServiceThree, true, [{mydata: "example information"}]);
ServiceLocator.get('ServiceThree').data; // {mydata: "example information"}

####Create a service object by yourself:

var serviceFour = new ServiceFour;

####Inject a previously created service object:

ServiceLocator.register(serviceFour.name, serviceFour);
// or
ServiceLocator.register('ServiceFour', serviceFour);

####Get an instance of service:

var ONE = ServiceLocator.get('ServiceOne');

####Call a mixin method:

ONE.getName(); // "ServiceOne"

####Call another mixin method:

ONE.setState("launched");

####Now call a mixin directly from "ServiceLocator":

ServiceLocator.get('ServiceOne').getState(); // "launched"

####Service number three have mixin but have no "name" property:

ServiceLocator.get('ServiceThree').getName(); // → "Service has no name!"

####Get currently instantiated services:

ServiceLocator.getAllInstantiate(); // ["ServiceOne", "ServiceThree", "ServiceFour"]

Instantiate all service objects but "ServiceTwo":

ServiceLocator.instantiateAll(function (serviceName) {
	if (serviceName === 'ServiceTwo') {
		return false;
	} else {
		return true;
	}
});

####Now without exceptions:

ServiceLocator.instantiateAll(); // → "Instantiate: ServiceTwo"

####Get currently instantiated services:

ServiceLocator.getAllInstantiate(); // ["ServiceOne", "ServiceTwo", "ServiceThree", "ServiceFour"]

###Register multiple service objects

Current state of registry inside Service Locator:

{
	"ServiceFour":  ▸Object
	"ServiceOne":   ▸Object
	"ServiceThree": ▸Object
	"ServiceTwo":   ▸Object
}

####Previosly set state:

ServiceLocator.get('ServiceOne').getState(); // "launched"

####Remove the instance, but keep the service. This removes any non-default set data in the service object:

ServiceLocator.removeInstance('ServiceOne');

####"ServiceLocator" will instantiate a new instance of the service object:

ServiceLocator.get('ServiceOne').getState(); // undefined
// → "Instantiate: ServiceOne"

As you can see, previously saved data won't be brought back.

####Deletes a service from "ServiceLocator" and returns its instance:

var unRegisteredService = ServiceLocator.unRegister('ServiceFive');
{
	__mixins: ["id", "setState", "getState", "getName"],
	id:       "ServiceFive",
	getState: ▸Function,
	prop:     ▸Array,
	setState: ▸Function,
}

####Same as above, but without mixins:

var unRegisteredServiceWithoutMixins = ServiceLocator.unRegister('ServiceFive', true);

Any mentions were removed, so:

ServiceLocator.get('ServiceFive'); // null
// → "Service is not registered: ServiceFive"

####Delete all registered services from "ServiceLocator" and return an array of their instances:

ServiceLocator.unRegisterAll();
{
	"ServiceFive":  ▸Object,
	"ServiceFour":  ▸Object,
	"ServiceOne":   ▸Object,
	"ServiceSix":   ▸Object,
	"ServiceThree": ▸Object,
	"ServiceTwo":   ▸Object,
}

####Same as above, but returned objects have their mixins removed:

ServiceLocator.unRegisterAll(true);