I'm curious what exactly decorators are in AngularJS. There isn't much information online for decorators save for a blurb in the AngularJS documentation and a brief (albeit interesting) mention in a youtube video.
As the Angular guys put it a decorator is:
Decoration of service, allows the decorator to intercept the service
instance creation. The returned instance may be the original instance,
or a new instance which delegates to the original instance.
I don't really know what that means, and I'm not sure why you would separate this logic from the service itself. For example if I wanted to return something different under different conditions I would just pass different arguments to the relevant functions or use another function sharing that private state.
I'm still kind of an AngularJS noob so I'm sure it's just ignorance and/or bad habits I've picked up.
A good use case of $provide.decorator is when you need to do minor "tweak" on some third-party/upstream service, on which your module depends, while leaving the service intact (because you are not the owner/maintainer of the service). Here is a demonstration on plunkr.
Decorators allow us to separate out cross-cutting concerns and allow services to preserve the single-responsibility-principle without worrying about "infrastructure" code.
Practical uses of decorators:
Caching: if we have a service which makes potentially expensive HTTP calls, we can wrap the service in a caching decorator which checks local storage before making the external call.
Debugging/Tracing: have a switch depending on your development/production configuration which decorates your services with debugging or tracing wrappers.
Throttling : wrap frequently triggered calls in a debouncing wrapper. Allows us to easily interact with rate-limited services, for example.
In all these cases, we limit the code in the service to its main responsibility.
decorator can intercept service instance created by factory, service, value, provider, and gives the options to change some instance(service) that is otherwise not configurable / with options.
It can also provide mock up instances for testing purpose, for example $http.
In simple word we can say that it’s like an extension method. For Ex. We have a class and it has two methods and at run time we want to add more method in it then we use Decorator.
We cannot use $provide.decorator with constants because we cannot change the constants they are heaving read only property.
In short decorators can be described as follows :-
A decorator function intercepts the creation of a service, allowing it
to override or modify the behavior of the service.
It uses the $provide service by angular and modify or replaces the implementation of another service
$provide.decorator('service to decorate',['$delegate', function($delegate) {
// $delegate - The original service instance,
// which can be replaced, monkey patched,
// configured, decorated or delegated to.
// ie here what is there in the 'service to decorate'
// This function will be invoked,
// when the service needs to be provided
// and should return the decorated service instance.
return $delegate;
}]);
Example:
$provide.decorator('$log', ['$delegate', function($delegate) {
// This will change implementation of log.war to log.error
$delegate.warn = $delegate.error;
return $delegate;
}]);
Applications
In addition to #JBland answer.
Application wide locale settings :-
You can find an example here
Changiging default behaviour of and existing implementation of a service by angular service :-
You can find an eample here
Switching behavior of a function in different environments.
Related
I want to set some user preferences in my angular app. I will get these preference from a REST api so I will need to make a http call. Once these have been fetched from the API, their values will not be modified.
What is the best practice in this case?
Can I make http calls in angular.module.value? Or use something like a provider? Or just write a service? What are the things to consider in any of these approaches?
What is the design pattern to be followed in this case?
You could create a service using the factory recipe. That will make the code a lttle cleaner and more modular.
Following that, you could put the user preferences on the $rootScope. This is a good case for a valid use of $rootScope, since your values are constants with application-wide applicability.
I am working on an AngularJS application that has some self-registering components. Concretely, there are some services that do not directly offer any public interface themselves; they merely register some internal objects in some directory provided by another service.
You can imagine the body of such a service's factory as follows:
var internalThing = {
// members ...
};
thingRegistryService.registerThing(internalThing);
return {};
Thus, I only need to ensure that the service gets loaded at some point.
The dilemma I'm facing is as follows: As the service provides no public functions and just needs to "be there", there is no reason to inject it anywhere. As it does not get injected, it never gets instantiated. As it never gets instantiated, the components within the service never register themselves, though.
I can inject the service the usual where in some service or controller that I know will get loaded - but then, I am basically leaving an unused argument in the code (which, if it is the last argument in the list, will even get outlined as an error based on the project's JSHint settings).
Alternatively, I can do the self-registration in a method in the service and call that wherever I inject the service. This would make the service injection "useful", but in turn I'd have to deal with multiple calls myself instead of relying on the built-in singleton mechanism of AngularJS's services.
Or ... should I go yet another route, by providing a method like registerThing somewhere that takes the service name as a string, and that will internally just invoke $injector.get? Of course, that evokes the question again where the correct place to put that kind of call would be.
A little background: This is part of a large project developed in a large team. Build and/or deployment magic somehow handles that any JavaScript code file committed to our VCS by any developer will be available to AngularJS's dependency injection. Thus, any JavaScript that needs to be added has to be provided as some kind of an AngularJS service, controller, etc.
What is the proper way to load such a self-registering service?
Right place to init your module is angular.module('yourModule').run block.
In case of "self-registering" I think it is better to have some implicit method for this:
angular.module('yourModule').run(['service'], function (service) {
service.init();
})
If your build system magically provides all JS code, is an import needed?
A self-registering architecture as your build system suggests should not require imports. The import JSHint errors are the cost of this magic.
I've used a similar behavior with namespace-like design. It can be used for self-registering techniques, although imports get tricky and does not work well with ES6 modules.
This is close to my point: http://blog.assaf.co/automating-component-registration-in-angularjs/
I just discovered how to share data between controllers using a service that stores an array and passes it by reference to the second controller.
Is there a way that the Service can protect the array from the first controller as that controller is only required pass an item to the service. The array is only used by the second controller.
ModalController - accepts input from user
MyService - takes the input from the user and stores it in an array -
ActionController - has a reference to the MyService array and displays it on the view
Above is the basic structure of the app.
Here is a jsfiddle of it
It looks like you're overdoing it. This cannot be done by means of the framework, and this cannot be solved by means of JavaScript, since the language has no access control.
MyService has both getChore and passChore methods as its public interface, and any unit that uses the service can both methods too. This is perfectly fine. If both controllers are developed by yourself and you have no real reasons to restrict the access, apply Occam's razor here and don't look any further.
If this were a library that is developed by you and will be used by third party, a method that shouldn't be used from the outside could be marked as 'internal' and named accordingly. AngularJS has the convention to prefix all internal things with $$.
On the other hand, TypeScript is intended to augment JavaScript with types and access control, so is possible to solve it this way, at least at design time (before TS source code was compiled to JS):
interface IWritableFooService {
setFoo();
}
interface IDuplexFooService extends IWritableFooService {
getFoo();
}
class FooService implements IDuplexFooService {
getFoo() {...}
setFoo() {...}
}
Considering that the service was defined as
app.service('fooService', FooService);
It can be injected in one place with restrictive type:
app.controller('BarController', function (fooService: IWritableFooService) {...});
And with loose type in another:
app.controller('BazController', function (fooService: IDuplexFooService) {...});
If BarController will try to use fooService.getFoo(), this will result in TypeScript compilation error.
This approach is an example of overengineering. Even if proper interface was specified, nobody can prohibit a developer to replace IWritableFooService with IDuplexFooService type at some point. OOP best practices originate from practical considerations, and it appears that there's none. But yes, it is possible to do this with TypeScript.
Ok so I was reading here
basically when I have this
MyApp = MyApp || {};
MyApp.settings = {
isFooEnabled: false
}
if I use the rootscope and want to check if isFooEnabled I have to inject the rootScope into whatever object I want to do the check.
How does that make sense?
What is the advantage of using $rootScope.isFooEnabled over using straight standard javascript MyApp.isFooEnabled?
what is better for what?
when should I use one over the other?
The $rootScope is the top-most scope. An app can have only one $rootScope which will be shared among all the components of an app. Hence it acts like a global variable. All other $scopes are children of the $rootScope.
The rootScope's variable is set when the module initializes, and then each of the inherited scope's get their own copy which can be set independently.
NOTE:
When you use ng-model with $rootScope objects then AngularJS updates those objects under a specific $scope of a controller but not
at global level $rootScope.
The $rootScope shouldn't be used to share variables when we have things like services and factories.
Finally, Angular FAQ says this at the bottom of the page: "Conversely, don't create a service whose only purpose in life is to store and return bits of data." See from here.
Actually, I would argue that you shouldn't use $rootScope in this case, you should create a separate service (or factory) that stores your settings, however, the usage and reasons are the same.
For simply storing values, the primary reason is consistency. Modules and dependency injection are a big part of angular to ensure you write testable code, and these all use dependency injection so that unit tests can be written easily (dependencies can be mocked). Whilst there are not many obvious gains from injecting a simple object, it's consistent with the way more complex code is accessed, and there is a lot to be said for that. On a similar note, if you were to upgrade your settings object to fetch data from the server (e.g. for environment specific settings), you might want to start unit testing that functionality, which you can't really do properly without modularising it.
There is also the (frankly weak) namespacing argument - what if another library you import uses window.MyApp?
TL;DR: It's a strongly recommended best-practice. It might seem a bit clunky now, but you'll benefit from doing it in the long run.
I am currently reading http://addyosmani.com/resources/essentialjsdesignpatterns/book/#mediatorpatternjavascript
I understand the mediator pattern as some sort of object which sets up publish and subscribe functionality.
Usually I am setting up objects which already provide subscribe(), publish() methods. Concrete Objects extend this base object so that subscribe() and publish() are always registered as prototype attributes.
As I understand right the mediator pattern is used to add the publish-subscribe-methods to an object.
What is the benefit of this practice? Isn't it a better practice to provide a base object with publish and subscribe functions than letting a mediator set up at construction?
Or have I understood the mediator pattern wrong?
As what I have learned from similar posts some time ago:
The mediator pattern provides a standard API for modules to use.
Let's have an example:
Your app's thousands of modules heavily rely on jQuery's $.post. If suddenly, your company had licensing issues and decided to move over to, for example, MooTools or YUI, would your look for all the code that uses $.post and replace them with something like MooTools.post?
The mediator pattern solves this crisis by normalizing the API. What the modules know is that your mediator has a post function that can do AJAX post regardless of what library was used.
//module only sees MyMediator.post and only knows that it does an AJAX post
//How it's implemented and what library is used is not the module's concern
jQuery.post -> MyMediator.post -> module
MooTools.post -> MyMediator.post -> module
YUI.post -> MyMediator.post -> module
The mediator serves as the "middle-man" for intermodule communication.
One problem in newbie JS development is when modules are interdependent. That is when:
MyClassA.something = MyClassB.method();
MyClassB.something = MyClassA.method();
But what if something is wrong in MyClassB and the developer took it out of the build. Would you look for and strip out all code in MyClassA that uses MyClassB so that it does not break due to the absence of MyClassB?
The mediator pattern's publish and subscribe pattern solves this by making the module subscribe to an event instead of directly interfacing with the other modules. The mediator acts as a collection of callbacks/subscriptions that are fired when events are published.
This "anonymous" subscribing results in partial loose-coupling. Modules would still need to know which modules to listen to or at least a set of events to listen to, but they are connected in a way that won't result in breakage if any one of them is taken out. All they know is that they subscribed to the event and will execute when that event happens - regardless of who fires it, if it fires at all, or if the trigger exists.
You can achieve mediation without using eventing (pub/sub).
In complex/sophisticated flows, it can be challenging to debug or reason about code that is purely event driven.
For an example on how you can create a mediator without pub/sub, you can take a look at my project jQueryMediator:
https://github.com/jasonmcaffee/jQueryMediator