Now returning to our project where we are pulling user profiles, we've made some good progress. We can now make real life API requests for data using $http (AJAX requests)!
But what happens if we want to have a bit more granular control over our code. Sometimes you'll want to manipulate your data before you send it over to the controller. That's where $q comes into play!
$q allows us to hold off on sending our data over until we're ready. It's fairly simple. All we need to do is edit our service.
- Inject $q into the service
var app = angular.module('userProfiles');
app.service('mainService', function($http, $q) {
this.getUsers = function() {
return $http({
method: 'GET',
url: 'http://reqr.es/api/users?page=1'
})
}
});
- Once injected we can begin using it by adding a deffered variable to handle it
var app = angular.module('userProfiles');
app.service('mainService', function($http, $q) {
this.getUsers = function() {
var deferred = $q.defer();
return $http({
method: 'GET',
url: 'http://reqr.es/api/users?page=1'
})
}
});
- Now let's add a promise to our service
var app = angular.module('userProfiles');
app.service('mainService', function($http, $q) {
this.getUsers = function() {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'http://reqr.es/api/users?page=1'
}).then(function(response) {
deferred.resolve(response)
})
return deferred.promise;
}
});
Right now, our code should still work the same, so what's the point of $q? Why are we adding all of this weird code to our service?
Well imagine you wanted to make a change to your data before you sent it over to the controller. For instance, currently we have this happening in our controller:
mainService.getUsers().then(function(dataFromService) {
$scope.users = dataFromService.data.data;
});
dataFromService.data.data??? We are loading a lot of unnecessary data into our $scope object. Rather than filter it out in our controller we can use $q to filter it out as we pull it through our service.
var app = angular.module('userProfiles');
app.service('mainService', function($http, $q) {
this.getUsers = function() {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'http://reqr.es/api/users?page=1'
}).then(function(response) {
var parsedResponse = response.data.data
deferred.resolve(parsedResponse)
})
return deferred.promise;
}
});
Now our controller can just take what it's given and not have to filter anything out. Like so:
var app = angular.module('userProfiles');
app.controller('MainController', function($scope, mainService) {
$scope.getUsers = function() {
mainService.getUsers().then(function(dataFromService) {
$scope.users = dataFromService;
});
}
$scope.getUsers();
});
Cool stuff!
Let's go ahead and do something a little less relevant, but more fun. Let's change everyones first_name in the service to Ralf.
var app = angular.module('userProfiles');
app.service('mainService', function($http, $q) {
this.getUsers = function() {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'http://reqr.es/api/users?page=1'
}).then(function(response) {
parsedResponse = response.data.data
for(var i = 0; i < parsedResponse.length; i++) {
parsedResponse[i].first_name = 'Ralf'
}
deferred.resolve(parsedResponse)
})
return deferred.promise;
}
});
Now all of our user's first names are Ralf. While it isn't a very good real world example, it's good to see how we can manipulate things. $q!