Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialjason chan
31,009 PointsWhat's happening here in the app? Angularjs
angular.module("todoListApp", [])
.controller('mainCtrl', function($scope, dataService){
// This line below
$scope.helloConsole = dataService.helloConsole;
$scope.learningNgChange = function () {
console.log("Input changed!");
};
$scope.todos = [
{"name": "Do Something"},
{"name": "Do Nothing"},
{"name": "Do bogus shit"},
{"name": "Do more shit"},
{"name": "Do stuff"},
{"name": "Do nothing"},
]
})
.service('dataService', function(){
this.helloConsole = function() {
console.log('This is hello console service!');
}
});
I don't understand this line of code. Help.
// This line below
$scope.helloConsole = dataService.helloConsole;
3 Answers
Russell Cousineau
1,541 PointsThis creates a service called dataService
:
service('dataService', function(){
this.helloConsole = function() {
console.log('This is hello console service!');
};
});
It's basically just an object that has a method helloConsole
attached to it.
When creating the controller, you injected the dataService
service into it:
controller('mainCtrl', function($scope, dataService)
And this:
$scope.helloConsole = dataService.helloConsole;
...is putting the dataService
method helloConsole
on your controller's scope.
If you were to call $scope.helloConsole()
now, you would see "This is hello console service!" logged, because that's how that method is defined in the dataService
service.
Hope this helps. Cheers.
Rock Hudson
27,595 PointsHey Jason... here is what is going on :)
Services and Factories are used to share functionality within an AngularJS Application.
$scope.helloConsole = dataService.helloConsole;
// This is saying, I want my variable in this controller to be equal to dataService's helloConsole Function
What you are seeing is re-usable code at its finest :)
David Hughes
5,063 PointsGreat explanation!
What are the differences in services and factories?
Anthony c
20,907 PointsSo, when we have multiple controllers who are using the same functionality, we can use a service so that we don't have to re-write the functionality over and over in each controller, and can instead just insert the service in each controller. This is shorter, and allows us to use that functionality still.
Is that the basic idea?
jason chan
31,009 Pointsso it's like caching.
Russell Cousineau
1,541 Pointsso it's like caching.
Not really. It's really just a way to write modular code that can be used across your application and written only once.
Let's say that you did want to implement some sort of cache, though. Imagine adding 2 to a number was a really expensive calculation that took a long time. You could write a method in a controller that added 2, like this:
myApp.controller('FrontPageController', function() {
this.addTwo = function(n) {
return n + 2;
};
});
Rather than just computing that every time you call addTwo
, you could cache the results each time the function is called, so that if you're ever adding 2 to the same value of n
you can get instant results. Here's what that could look like:
var addTwoResults = {};
this.addTwo = function(n) {
if (angular.isUndefined(addTwoResults[n])) {
addTwoResults[n] = n + 2;
}
return addTwoResults[n];
};
That's the basic premise of caching.
Now imagine that you need to add 2 in a different part of the application. But you know that you're going to want to cache the results (remember... we're pretending adding 2 is an expensive, time-consuming calculation). But you don't want to have two copies of that function, because if you ever needed to change the behavior of addTwo
you'd have to do it in 2 places (this is the DRY Principle).
This is where services come into play.
Let's add a myComputations
service to the app, with our addTwo
functionality contained in the service:
myApp.service('myComputations', function() {
var addTwoResults = {};
this.addTwo = function(n) {
if (angular.isUndefined(addTwoResults[n])) {
console.log('computing addTwo(' + n + ')');
addTwoResults[n] = n + 2;
}
return addTwoResults[n];
};
});
Now we can inject the myComputations
service into the controller(s) in our app:
myApp.controller('myController', function(myComputations) {
console.log('controller asking for result of 42+2');
myComputations.addTwo(42); // should see "computing addTwo(42)" in console
console.log('controller asking again');
myComputations.addTwo(42); // should not see anything in console this time
});
This functionality can now be shared across the app, and the code is only written once!
Just for fun, here's a version of the myComputations
service where addTwo
takes 3 seconds to compute...
myApp.service('myComputations', function($q, $timeout) {
var addTwoResults = {};
// this holds promises (read about them [here](https://docs.angularjs.org/api/ng/service/$q))
var addTwoPromises = {};
var computeAddTwo = function(n) {
// prevent the same computation from getting done more than once if
// if it's called a second time before the first time returns the result
if (angular.isDefined(addTwoPromises[n])) {
return addTwoPromises[n];
}
// first define a deferred, which will give us a promise
var deferred = $q.defer();
addTwoPromises[n] = deferred.promise;
// now resolve the deferred after 3 seconds
$timeout(function() {
deferred.resolve(n + 2);
}, 3000);
// return a promise, which can be viewed by the caller to get the result
return addTwoPromises[n];
};
this.addTwo = function(n) {
if (angular.isUndefined(addTwoResults[n])) {
console.log('computing addTwo(' + n + ')');
addTwoResults[n] = computeAddTwo(n);
}
return addTwoResults[n];
};
});
myApp.controller('myController', function(myComputations) {
console.log('controller asking for result of 42+2');
// we now need to use `then` to get the result, since this is now an asynchronous function call
myComputations.addTwo(42).then(function(result) {
// should see "computing addTwo(42)" in console
console.log('result', result);
console.log('controller asking again');
myComputations.addTwo(42).then(function(result) {
// should not see "computing addTwo(42)" in console this time
// also, it should print the result instantly (instead of after 3 more seconds)
console.log('result', result);
});
});
});
I wrote this in plunkr if you want to see it work.
Sorry for the essay response, just got bored and rambled!