AngularJS: Introduction to Services

All AngularJS services are “singletons”, that is, there is only one instance of a specific service per Angular application to carry out some specific task.

Up until now, we have been working on the examples where all the data for the model has been included in the code.   Although, this is fine for instructional purposes this is quite limiting in scope.  Communicating with a server becomes essential in order to pull down data from files, databases, external systems via API calls, etc.    AngularJS provides two services for this:

  • $http: this service makes use of low-level HTTP calls via XMLHttpRequest or JSONP
  • $resource: this service is dedicated to the REST API calls

Using services, allows developers a great way of separating logic from their controllers. AngularJS makes it very easy for developers to create their our own services for any complex operation.

In this tutorial, we will be specifically discussing the use of $http service to make AJAX and JSONP calls.   In a subsequent post, I will discuss $resource, which, as stated above, is more  appropriate for REST API calls.

1. AngularJS $http Service

The $http service provides a simple and elegant way to communicate with a web server using the HTTP protocol.  I will mention, as a side bar, that our AJAX calls cannot be sent to a different domain from where the HTML page was loaded from without making some slight modifications on the server-side code.

This restriction on modern browsers was necessary to counter the security threat of cross-site scripting.   However,  with the explosion of AJAX and the rise of clients pulling data from various sources, many of which reside on different domains, changes have been coming at an astonishing pace.

Such “cross-domain” requests would otherwise be forbidden by web browsers, per the same origin security policy.  CORS (Cross Origin Resource Sharing) defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request.

Today, many of the modern browsers (Internet Explorer* 10+, Firefox 29+, Chrome 34+, Safari 6+ and Opera 21+) support CORS and can make requests to other domains so long as some provisions are made on the target server.  I only mention this, because as you will see, I needed to make some changes to the header of the response object in my nodeJS application since it was technically running as a standalone web server (thereby using a different domain) then from the one hosting the AngularJS web application.

1.1 Let’s look at our sample application

angularJS_ServicesConsider the typical scenario where we need to access some resource from a back-end data source.  In our example, I have a web server running Apache Tomcat which is hosting the application on my localhost at port 7777.   I then created a simple nodeJS web application running on port 8888 (this is cross domain) to pull in data from an array.   In this first example, I decided not to pull from any additional external data source, but in subsequent examples, we will pull data from files and then from mongoDB database.

Take a few minutes and spend some time reviewing what a typical scenario would look like using the diagram I have provided.

1.2 Internal Services

AngularJS provides many internal services that we can use in our applications.   These are just some of them: $animate, $location, $log,  $window, $httpBackend and $route.  For a complete list of services provided by AngularJS I would recommend reviewing the Angular API Reference.

1.3 The Javascript

(function() {var app = angular.module("app", []);

app.controller("HttpCtrl", function($http) {
	var app = this;
	var response = $http.get("http://localhost:8888/");
	response.success(function(data) {
			app.books = data;
		})
	response.error(function(data, status, headers, config) {
		alert("AJAX failed to get data, status=" + status);
	})
});
})();

 

1.4 The HTML

<!DOCTYPE html>
<html ng-app="app">
<head>
    <title>Angular Simple Service</title>
    <link rel="stylesheet" type="text/css" href="include/styles.css">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js">
    </script>
    <script type="text/javascript" src="include/app2.js">
</head>

<body>
	</script>
	<div ng-controller="HttpCtrl as app" >
		<table class="striped">
			<tr>
				<th>Title</th>
				<th>Author</th>
				<th>Price</th>
				<th>ISBN</th>
			</tr>
			<tr ng-repeat="book in app.books">
				<td>{{ book.title }}</td>
				<td align="center">{{ book.author }}</td>
				<td align="right">{{ book.price | currency}}</td>
				<td align="center">{{ book.isbn }}</td>
			</tr>
		</table>
	</div>
</body>
</html>

1.5 NodeJS Server

/*
  Using Node.js to create a version simple HTTP server
  that will output JSON data back to the user.

  To make things simple I have created a JSON book object
  that will be used.

*/ 

var http = require("http");

var data = [
            { title: "Charlotte's Web", "price": 6.35, "isbn": "978-0739477076", author: "E. B. White"},
            { title: "Great Expectations", "price": 2.87, "isbn": "978-0486415864", "author": "Charles Dickens"},
            { title: "Harry Potter and the Sorcerers Stone", "price": 6.92, "isbn": "978-0590353427", "author": "J.K. Rowling"},
            { title: "Beloved", "price": 8.75, "isbn": "978-1400033416", "author": "Toni Morrison" },
            { title: "Moneyball: The Art of Winning an Unfair Game", "price": 9.01, "isbn": "978-0393324815", "author": "Michael Lewis"},
          ];

var responseString = JSON.stringify(data);

var host = '127.0.0.1';
var port = 8888;

console.log("Data available on server: " + responseString);
console.log("Starting http server...");

/*
	Simple HTTP server using NodeJS, support for CORS required,
	otherwise, Mozilla and Chrome browsers reject responses
	notice some access-controls-allow-* added to header
*/

var headers = {
		'Content-type':'application/json',
		'Content-Length': responseString.length,
		'Access-Control-Allow-Origin' : '*',
		'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
		'Access-Control-Allow-Headers': 'X-Requested-With, content-type'
	};

var server = http.createServer(function(req, res) {
	console.log("Received request " + req.url);
	res.writeHead(200, headers);
	res.end(responseString);
});

server.listen(port, host, function() {
	console.log("Listening on " + host + ":" + port);
});

2. Connecting to MongoDB Database

mongoLab_logoFor this next example, we will connect to a mongoDB database. I am using MongoLab (MongoDB-as-a-Service), which allows us to quickly create a database and give us easy accessibility from a web server using the REST API.

For this example, I inserted the following documents into the collection.

mongoLab_collection

MongoLab provides a very simple and elegant way to access your mongoDB database using the following REST API syntax:

https://api.mongolab.com/api/1/databases/<db-name>/collections/<collection-name>?apiKey=<user-api-key>

Using my APIKey, click the link to see the raw JSON data from mongoDB

2.1 Using CURL

cURL is a command line tool for getting or sending files using URL syntax.

Since cURL uses libcurl, it supports a range of common Internet protocols, currently including HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, LDAP, LDAPS, DICT, TELNET, FILE, IMAP, POP3, SMTP and RTSP. On a Unix or Linux system using cURL:

$ curl -i -X GET https://api.mongolab.com/api/1/databases/library/collections/books?apiKey=Bfl0MpDXd9_HMSv754 M_y6shYqYtUPp2

cURL Output

HTTP/1.1 200 OK
Date: Sun, 9 Feb 2014 23:20:45 GMT
Server: Apache/2.2.22 (Ubuntu)
Expires: Tue, 01 Feb 2000 08:00:00 GMT
Last-Modified:  Sun, 9 Feb 2014 23:20:45 GMT
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Pragma: no-cache
X-Frame-Options: DENY
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json;charset=utf-8
[ { "_id" : { "$oid" : "5429c1b0e4b0142af66429b8"} , "title" : "Charlotte's Web" , "price" : 6.35 , "isbn" : "
978-0739477076" , "author" : "E. B. White"} , { "_id" : { "$oid" : "5429c211e4b0142af66429b9"} , "title" : "Gr
eat Expectations" , "price" : 2.87 , "isbn" : "978-0486415864" , "author" : "Charles Dickens"} , { "_id" : { "
$oid" : "5429c2a3e4b0142af66429bf"} , "title" : "Moneyball: The Art of Winning an Unfair Game" , "price" : 9.0
1 , "isbn" : "978-0393324815" , "author" : "Michael Lewis"} , { "_id" : { "$oid" : "5429cb55e4b0142af6642a18"}
, "title" : "Black Beauty" , "price" : 4.05 , "isbn" : "978-0486407883" , "author" : "Anna Sewell"} , { "_id"
: { "$oid" : "5429cbbde4b0142af6642a22"} , "title" : "Diary of a Wimpy Kid" , "price" : 7.88 , "isbn" : "978-
0810993136" , "author" : "Jeff Kinney"} , { "_id" : { "$oid" : "5429cc13e4b0142af6642a26"} , "title" : "The Bo
rrowers" , "price" : 3.94 , "isbn" : "978-0152047375" , "author" : "Mary Norton"} , { "_id" : { "$oid" : "5429
cc9de4b0142af6642a2d"} , "title" : "Among the Hidden" , "price" : 4.99 , "isbn" : "978-0689824753" , "author"
: "Margaret Peterson Haddix"} ]

2.3 The Javascript

var app = angular.module("app", []);

app.controller("HttpCtrl", function($http) {
var app = this;
var response = $http.get("https://api.mongolab.com/api/1/databases/library/collections/books?apiKey=Bfl0MpDXd9_HMSv754M_y6shYqYtUPp2");
response.success(function(data, status, headers, config) {
app.books = data;
})
response.error(function(data, status, headers, config) {
alert("AJAX failed to get data, status=" + status);
})
});

2.4 Output

mongoLab_output

3. What’s Next

From here, we will go on to continue to work with AngularJS services.   This time, we will create our own services and show you the different ways you can use custom services.

References

Please Share Us on Social Media

Facebooktwitterredditpinterestlinkedinmail

Leave a Reply

Your email address will not be published. Required fields are marked *