Creating reusable singleton services

Loading

In AngularJS, singleton services are reusable components that provide shared logic and state across an application. They are instantiated once and used wherever needed.

Why Use Singleton Services?

Data Sharing โ€“ Share data across multiple controllers.
Code Reusability โ€“ Encapsulate business logic in one place.
Performance Improvement โ€“ Prevent redundant object creation.
Dependency Injection โ€“ Easily manage dependencies.


1. Creating a Singleton Service in AngularJS

A singleton service is instantiated once and remains the same throughout the application lifecycle.

Using .service()

var app = angular.module("myApp", []);

// Singleton Service
app.service("UserService", function () {
this.user = { name: "John Doe", email: "john@example.com" };

this.getUser = function () {
return this.user;
};

this.setUser = function (userData) {
this.user = userData;
};
});

// Controller using the service
app.controller("UserController", function ($scope, UserService) {
$scope.user = UserService.getUser();

$scope.updateUser = function () {
UserService.setUser({ name: "Jane Doe", email: "jane@example.com" });
$scope.user = UserService.getUser();
};
});

๐Ÿ”น How it Works:

  • UserService is a singleton that holds user data.
  • getUser() retrieves the shared data.
  • setUser() updates the shared state across the app.

2. Creating a Singleton with Factory

A factory returns an object, making it more flexible than a service.

app.factory("UserFactory", function () {
var user = { name: "John Doe", email: "john@example.com" };

return {
getUser: function () {
return user;
},
setUser: function (userData) {
user = userData;
}
};
});

Key Differences from .service()

  • Factory returns an object explicitly instead of using this.
  • Useful for adding private variables and complex logic before returning an object.

3. Making an API-Driven Singleton Service

Often, services fetch data from an API and provide it throughout the app.

app.service("UserService", function ($http) {
var user = null;

this.getUser = function () {
if (!user) {
return $http.get("https://jsonplaceholder.typicode.com/users/1").then(function (response) {
user = response.data;
return user;
});
}
return Promise.resolve(user);
};
});

๐Ÿ”น Benefits

  • Data is fetched only once.
  • Promise.resolve(user) prevents redundant API calls.

4. Using a Provider for Configurable Singleton Services

If a service needs configuration before being used, a provider is ideal.

app.provider("ConfigService", function () {
var apiUrl = "https://default-api.com";

this.setApiUrl = function (url) {
apiUrl = url;
};

this.$get = function () {
return {
getApiUrl: function () {
return apiUrl;
}
};
};
});

// Configure the service before the app runs
app.config(function (ConfigServiceProvider) {
ConfigServiceProvider.setApiUrl("https://jsonplaceholder.typicode.com");
});

app.controller("ConfigController", function ($scope, ConfigService) {
$scope.apiUrl = ConfigService.getApiUrl();
});

๐Ÿ”น Use Case:

  • Configure an API base URL dynamically before the app loads.

5. Choosing the Right Singleton Approach

MethodBest For
.service()Simple objects with methods
.factory()More flexibility & complex logic
.provider()Services requiring configuration

Leave a Reply

Your email address will not be published. Required fields are marked *