Use Javascript Object to Angular Service - javascript

I am trying to add functions to a JS Object which will be used as a singleton service.
angular
.module('app.steps')
.factory('createStepsService', createStepsService);
createStepsService.$inject = [];
/* #ngInject */
function createStepsService() {
var steps;
var service = {
newSteps: function (current_step, total_steps) {
if (!steps) {
return new Steps(current_step, total_steps);
}
}
};
return service;
function Steps(current_step, total_steps) {
this.c_step = current_step;
this.t_step = total_steps;
}
Steps.prototype = {
addSteps: function (num) {
this.c_step += num;
},
setLastStep: function () {
this.lastStep = this.c_step = this.t_step;
}
};
}
When I run this line from the controller, I am not able to access
addSteps / setLastStep methods.
vm.createStepsService = createStepsService.newSteps(1, 3);
Why I don't see these methods? Were they created?
Thanks.

Your steps.prototype code is never ran.
This is because it appears after the return.
Change the order of your code to this:
/* #ngInject */
function createStepsService() {
var steps;
function Steps(current_step, total_steps) {
this.c_step = current_step;
this.t_step = total_steps;
}
Steps.prototype = {
addSteps: function (num) {
this.c_step += num;
},
setLastStep: function () {
this.lastStep = this.c_step = this.t_step;
}
};
var service = {
newSteps: function (current_step, total_steps) {
if (!steps) {
return new Steps(current_step, total_steps);
}
}
};
return service;
}
The reason that you can have a function declared before a return is because of JavaScript variable and function hoisting.

Your problem is that you are creating Steps.prototype after a return statement, so it will never be read.

In AngularJS, services are singletons objects that are instantiated only once per app.
And the factory() method is a quick way to create and configure a service.
It provides the function's return value i.e. Need to create an object, add properties to it, then it will return that same object.
For ex:
angular
.module('myApp',[])
.factory("createStepService", function(){
var stepServiceObj = {};
var c_step = 0;
var t_steps = 0;
var last_step = 0;
stepServiceObj.setCurrentStep = function(current_step){
c_step = current_step;
console.log('c_step1: ',c_step);
};
stepServiceObj.getCurrentStep = function(){
return c_step;
};
stepServiceObj.setTotalStep = function(total_steps){
t_steps = total_steps;
};
stepServiceObj.getTotalStep = function(){
return t_steps;
};
stepServiceObj.setLastStep = function(){
last_step = c_step = t_step;
};
stepServiceObj.getLastStep = function(){
return last_step;
};
stepServiceObj.addSteps = function(num){
return c_step += num;
};
return stepServiceObj;
});

Related

Javascript function does not return the right value

So i have this code:
function Class1() {
this.i = 1;
var that=this;
function nn() {
return 21;
}
this.aa = function() {
nn();
};
this.bb = function() {
this.aa();
};
this.cc = function() {
this.bb();
};
}
var o = new Class1();
var b=o.cc();
alert(b); //undefined
But when the alert is fired, I get an undefined error and not 21, Does the private method can not use a return? Thanks!
When using the function() {} syntax to define a function, you always explicitly need to return the value, i.e. not only from nn, but from all intermediate functions as well.
function Class1() {
this.i = 1;
var that = this;
function nn() {
return 21;
}
this.aa = function() {
return nn();
}
this.bb = function() {
return this.aa();
}
this.cc = function() {
return this.bb();
}
}
var o = new Class1();
var b = o.cc();
alert(b); // "21"
Apart from the answer above, the 'this' context seems weird in your functions. Maybe you are better of with arrow functions if you dont want to bind the this context to each function. I also think that it is better to actually separate private and public functions when using a 'class' like this.
function Class1() {
var _nn = function () {
return 21;
}
var _aa = function () {
return _nn();
}
var _bb = function () {
return _aa();
}
var cc = function () {
return _bb();
};
return {
cc
};
}
var o = new Class1();
var a = o.cc();
console.log(a);
Much easier to understand that it is only cc that is a public function.
So with arrow function it would instead look like this, and you can use the Class1 this context inside of your private functions without doing
var that = this; or using bind.
function Class1() {
this.privateThing = 'private';
var _nn = () => { return this.privateThing; };
var _aa = () => { return _nn(); };
var _bb = () => { return _aa(); };
var cc = () => { return _bb(); };
return {
cc
};
}

Can't have access to a variable using call in Javascript

I'm studying Javascript and learning how to use call. I created this script and I don't know why I can't have access to this variable Time.
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {});
var myNewObj = new MyObject.Runner(1000); myNewObj.newTest('1', function() {
console.log(this.time) //output: undefined
});
So how can I get time value inside newTest function?
Issue is in newTest function
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
Here this is pointing to test and not Runner. You will have to save context in a variable and then set it in call.
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
.call + self
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
var self = this;
var test = function() {
return execute.call(self);
}
myFunctionArray.push(test);
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
.bind
As commented, you can even use .bind
var MyObject;
(function(MyObject) {
var Runner = (function() {
function Runner(time) {
this.time = time;
}
var myFunctionArray = [];
Runner.prototype.execute = function() {
myFunctionArray[0]();
}
Runner.prototype.newTest = function(index, execute) {
myFunctionArray.push(execute.bind(this));
}
return Runner;
})();
MyObject.Runner = Runner;
})(MyObject || (MyObject = {}));
var myNewObj = new MyObject.Runner(1000);
myNewObj.newTest('1', function() {
console.log(this, this.time) //output: undefined
});
myNewObj.execute()
When you declare your Runner function, you've actually declared a function that takes no arguments that then itself declares a function called Runner that takes one argument.
Actually In this code snippet :
Runner.prototype.newTest = function(index, execute) {
var test = function() {
return execute.call(this);
}
myFunctionArray.push(test);
}
this will reference to test variable (as per constructor invocation pattern)
So, to pass right variable cache the value of this in another variable and then pass that to function.

Issue with creating a reusable method

What's the best way to refactor the following randomizing code into a reusable method? I want to put this part into a reusable method ==>$scope.randTarotImg = $scope.tarotImg[Math.floor(Math.random() * $scope.tarotImg.length)];
I tried the following and it's not working:
function randTarotImg(){
$scope.randTarotImg = $scope.tarotImg[Math.floor(Math.random() * $scope.tarotImg.length)];
}
$scope.onClick = function() {
randTarotImg();
};
Here's the relevant code block:
.controller('TarotCtrl', function ($scope) {
$scope.tarotImg = [];
for (var i=1;i<=6;i++) {
$scope.tarotImg.push(i);
}
$scope.randTarotImg = $scope.tarotImg[Math.floor(Math.random() * $scope.tarotImg.length)];
$scope.onClick = function() {
$scope.randTarotImg = $scope.tarotImg[Math.floor(Math.random() * $scope.tarotImg.length)];
};
})
var arr = [1,2,3,4,5,6,7,8];
function getRandomElement(arr) {
return arr[Math.floor(Math.random()*arr.length)];
}
console.log(getRandomElement(arr));
In your case:
.controller('TarotCtrl', function($scope) {
$scope.tarotImg = [];
for (var i = 1; i <= 6; i++) {
$scope.tarotImg.push(i);
}
function getRandomElement(arr) {
return arr[Math.floor(Math.random()*arr.length)];
}
$scope.randTarotImg = getRandomElement($scope.tarotImg);
$scope.onClick = function() {
$scope.randTarotImg = getRandomElement($scope.tarotImg);
};
});

JavaScript function chaining using the singleton pattern

I have a small piece of code written like in below.
var MY = MY || {};
MY.Farm = (function () {
var add = function(x){
console.log(x)
return this + this;
};
return {
add: function(x){
return add(x);
}
}
});
On a separate file I create sheep an instance of MY.Farm
var sheep = new MY.Farm()
I want to be able to call the function like the following with an output 6
sheep.add(3).add(2).add(1)
Any ideas how I can achieve this? What are the changes required to the MY.Farm snippet to accommodate this?
Thanks in advance.
Something like this
var MY = MY || {};
MY.Farm = (function () {
var x=0;
return {
add: function(newX){
if(typeof(newX) !="undefined") {
x+=newX;
return this;
}
return x;
}
}
});
var sheep = MY.Farm();
console.log( sheep.add(2).add(4).add());
http://jsfiddle.net/7q0143er/
You're not too far off. The trick is you need to keep track of the value somewhere, like in a private variable, and add needs to return this. Finally, you need a way to get the value out when you're done:
MY.Farm = function () {
var total = 0;
return {
add: function(x) {
total += x;
return this;
},
value: function() {
return total;
}
};
};
var sheep = new MY.Farm();
sheep.add(3);
console.log(sheep.value()); // => 3
console.log(sheep.add(1).add(2).value()); // => 6

A Javascript function which creates an object which calls the function itself

I am trying to make an angular service that returns a new object.
That's fine and good and works. new MakeRoll() creates an instance. But self.add, near the end also calls new MakeRoll() and that doesn't create an instance when I call add like I think it should.
I'm probably doing this all wrong but I haven't been able to figure it out.
var services = angular.module('services', []);
services.factory('Roll', [function() {
var MakeRoll = function () {
var self = {};
self.rolls = [];
self.add = function(number, sizeOfDice, add) {
var newRoll = {};
newRoll.number = number || 1;
newRoll.sizeOfDice = sizeOfDice || 6;
newRoll.add = add || 0;
newRoll.rollDice = function() {
var result = 0;
var results=[];
for (var i = 0; i < newRoll.number; i++) {
var roll = Math.floor(Math.random() * newRoll.sizeOfDice) + 1;
result += roll;
results.push(roll);
}
newRoll.results = results;
newRoll.result = result;
newRoll.Roll = new MakeRoll();
};
self.rolls.push(newRoll);
return self;
};
self.remove = function(index) {
self.rolls.splice(index, 1);
};
self.get = function(index) {
return self.rolls[index];
};
return self;
};
return new MakeRoll();
}
]);
angular service is designed to be singleton to accomplish some business logic, so don't mix up plain model with angular service. if you want to have more objects, just create a constructor and link it in service to be operated on.
function MakeRoll() {
...
}
angular.module('service', []).factory('Roll', function () {
var rolls = [];
return {
add: add,
remove: remove,
get: get
}
function add() {
// var o = new MakrRoll();
// rolls.push(o);
}
function remove(o) {
// remove o from rolls
}
function get(o) {
// get o from rolls
}
});

Categories

Resources