What is the meaning of enforce parameter in AngularJS Factory - javascript

I was going through the details of how angular actually creates factory just by using module.factory() method.
I found that internally angular uses following method which internally uses provider only
function factory(name, factoryFn, enforce)
So my question is regarding the third parameter enforce of this function ,what it actually does.

When creating an Angular service or factory, behind the scenes, Angular eventually uses the same function for both:
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
When creating a service, a return value is generally not sent, and behind the scenes, Object.create() is called to create an object containing the sayHello method.
app.service('MyService', function () {
this.sayHello = function () {
console.log('hello');
};
});
However, when creating a factory, an object literal is returned:
app.factory('MyService', function () {
return {
sayHello: function () {
console.log('hello');
};
}
});
Basically, enforce is used to enforce a return value. It's not just a question of "Is this a service or factory?" since you can still return an object literal from a service if you wanted to:
app.service('MyService', function () {
return {
sayHello: function () {
console.log('hello');
};
}
});
Regarding the question: "Which should you use?" check out this:
http://blog.thoughtram.io/angular/2015/07/07/service-vs-factory-once-and-for-all.html

Related

How to escape "this" problem in a javascript class?

get_O3(e)
{
e.preventDefault();
let station = document.getElementById(e.target.id);
let lon = station.getAttribute('lon');
let lat = station.getAttribute('lat');
let code_station = station.getAttribute('code');
this.get_previsions(lon, lat, "O3").bind(this).then((data) =>
{
console.log(data);
});
}
I have a "this" problem, when i call the function get_previsions i get the error :
Uncaught TypeError: this.get_previsions is not a function.
It might be because of the (e) parameter because when i do a console.log(this) it returns the target. I would like that this == my class.
Thanks for the help
At any given point you can check what the current this reference is pointing to by doing the 4 following rules:
New: Was the function called using new then the this points to the new instance.
Explicit Binding: Was the function called using Function#call, Function#apply or Function#bind
Implicit Binding: Was the function called by its owner? (i.e. owner.foo() or owner["bar"]())
Default Rule: If none of the other rules happen then this is set to the window object if the script is running in "use strict" mode otherwise undefined.
Event-listeners call a function using Explicit binding (callBack.call(target, ...)) so the this reference gets set to the target. To change the this reference you either need to wrap it and call it implicitly or use Function#bind.
Implicit call Example (+ closure):
var something = {
foo: function() {
var self = this;
addEventListener("click", function(e) {
self.bar(e);
});
},
bar: function() {
}
};
Explicit call Example (Function#bind):
var something = {
foo: function() {
addEventListener("click", this.bar.bind(this));
},
bar: function() {
}
};
I'm assuming you have a class defined similar to
class thing {
get_O3(e) { ... },
get_previsions() { ... }
}
There are a few options for you. First option, you can bind all functions to this in the constructor:
class thing {
constructor () {
this.get_03 = this.get03.bind(this);
this.get_previsions = this.get_previsions.bind(this);
}
get_O3(e) { ... },
get_previsions() { ... }
}
This can get awkward, especially if you have many functions. You can write a helper bindAll function, but a less awkward/verbose solution is to use a factory method instead, bypassing this altogether:
function makeThing {
const thing = {
get_O3(e) {
...
thing.get_previsions();
},
get_previsions() { ... }
};
return thing;
}
Eric Elliot on Medium has some good reading on the topic if you want to get more in depth.

How to call a factory method dynamically coming from variable?

I have a service which will return the name of factory. I already injected all the factories into controller. I need to use the variable to call the method inside that factory. I know i can use
if(var == 'factoryname') {
factoryname.method()
}
but i don't want those if conditions because i have number of factories. Is there any way to call a method inside that factory like in java script
window[var]
You should consider storing all of your factories on an object:
var factories = {
factoryA: { method: function() {} },
factoryB: { method: function() {} },
};
var factory = 'factoryA';
factories[factory].method();

Returning function from AngularJS factory

I'm trying to understand what the purpose is of the return part of this AngularJS factory method means?
return {
getMessages: getMessages
};
What happens if we added a new method to this factory called getAnotherMessage(), would we need to update this return segment?
myModule.factory('HelloWorld', function($q, $timeout) {
var getMessages = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(['Hello', 'world!']);
}, 2000);
return deferred.promise;
};
return {
getMessages: getMessages
};
});
factory is a provider constructor:
factory(fn) - registers a service factory function, fn, that will be
wrapped in a service provider object, whose $get property will contain
the given factory function.
Thus when the factory is first loaded by Angular it executes the function that's passed in and stores whatever is returned as the provider.
In other words, the following is run once, and only once- during bootstrapping:
var getMessages = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(['Hello', 'world!']);
}, 2000);
return deferred.promise;
};
return {
getMessages: getMessages
};
The above gets a reference to the getMessage function and attaches it to the property getMessages inside the returned singleton object.
When the provider is then injected into your code, that returned object is what is passed in giving you access to the HelloWorld.getMessages function (and any other properties in the returned object).
So, yes, if you want to associate another property, such as a function, with the provider (that the factory constructs) you need to include it as a property of the returned singleton object:
return {
getAnotherMessage: function() { ... },
getMessages: getMessages
};
You can also declare an empty object first and add functions into the object
and finally return the object.
myModule.factory('HelloWorld', function($q, $timeout) {
var myobject = {};
myobject.getMessages = function() { ... };
myobject.getAnotherMessages = function() { ... };
return myobject;
});

Setter functions in angular providers

From my understanding factories are an abstraction over Angular's providers, which allow you to return data with less lines of code. However, providers provide more flexibility in that you can better define the service's functionality. I'm still really confused on how to call a simple function from a provider. Everyone seems to be doing them differently and I cannot get mine to work:
myApp.provider('myProvider', function() {
myVar = true;
$get: function() {
return {
myVar: myVar,
}
},
toggleFalse = function() {
myVar = false;
},
})
myApp.controller('myController', function($scope, myProvider) {
myProvider.toggleFalse();
});
This does not seem to work - and I'm having trouble understanding services in general. It says toggleFalse is not defined. How do you properly define a setter function on an Angular service that can be controlled through a controller?
If you do console.dir(myProvider), you'll see that you are getting the object returned from $get. You need to put the function on the returned object:
$get: function() {
return {
myVar: myVar,
toggleFalse: function() {
myVar = false;
},
}
},
This is a simple question of closure.
If you want every instance to have a unique everything, then store everything inside $get.
If you want the majority of the object to be unique, but have some methods or objects/arrays that every instance shares with each other, then define those in the function closure outside of $get and append them to the object returned from $get.
... ("myProvider", function () {
var sharedValue = 19,
sharedFunction = function () {
sharedValue += 1;
return shared value;
};
return {
$get : function () {
return {
unique : 1,
shared : sharedFunction
};
}
};
This isn't an Angular issue, so much as a core piece of JS's behaviour, which happens to be inside of an Angular paradigm.

javascript organisation

I came across this Q/A on javascript code organisation.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Currently I do this,
var DED = new Object;
DED = {
sidebar : {
method_1 : function (data){
//some stuff
},
method_2 : function(data){
//do more
}
},
main : {
//.......
},
globalVariables : {
//...
}
}
What is the advantage of one over the other?
Warning: newbie here.
As indicated, that method uses closures to implement private functions and data. It's an alternative to the constructor method (below). E.g.
var DED = new (function()
{
var private_var;
function private_method()
{
// do stuff here
}
this.method_1 = function()
{
// do stuff here
};
this.method_2 = function()
{
// do stuff here
};
})();
With the DED method shown in your question, there is no constructor. Rather the function returns an object created from an object literal. The functions in that object have the private variable and method closed into them.
What you return from the anonymous self-calling function (function(){})() is the interface you publish for your "module" (DED).
DED.method_1() is public. private_method/private_var are not accessible from outside but everything inside of your self-calling function has access to them.
If you like this kind of access-control this is a good way to prevent other developer from accidentally messing with the internals of your module. In a lot of cases i'd just go for a naming convention like a leading underscore to indicate internals.
Javascript is very dynamic and if someone really wants to mess with code they have no write-access to they will be able to do so. Edit: This turns out to be a wrong assuption and not the case for private data in constructors or closures. Please, see: http://www.crockford.com/javascript/private.html

Categories

Resources