blob: 26f69752a6ff5f40c9f82f5b8bc18bad225012ea [file]
<a href='http://github.com/angular/angular.js/edit/master/docs/content/guide/services.ngdoc' class='improve-docs btn btn-primary'><i class="glyphicon glyphicon-edit">&nbsp;</i>Improve this doc</a>
<h1 id="services">Services</h1>
<p>Angular services are substitutable objects that are wired together using <a href="guide/di">dependency</a>
injection (DI). You can use services to organize and share code across your app.</p>
<p>Angular services are:</p>
<ul>
<li>Lazily instantiated – Angular only instantiates a service when an application component depends
on it.</li>
<li>Singletons – Each component dependent on a service gets a reference to the single instance
generated by the service factory.</li>
</ul>
<p>Angular offers several useful services (like <a href="api/ng/service/$http"><code>$http</code></a>), but for most applications
you&#39;ll also want to <a href="guide/services#creating-services">create your own</a>.</p>
<div class="alert alert-info">
<strong>Note:</strong> Like other core Angular identifiers built-in services always start with <code>$</code>
(e.g. <code>$http</code>).
</div>
<h2 id="using-a-service">Using a Service</h2>
<p>To use an Angular service, you add it as a dependency for the component (controller, service,
filter or directive) that depends on the service. Angular&#39;s <a href="guide/di">dependency injection</a>
subsystem takes care of the rest.</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-example108@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-example108"
module="myServiceModule">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div id=&quot;simple&quot; ng-controller=&quot;MyController&quot;&gt;&#10; &lt;p&gt;Let&#39;s try this simple notify service, injected into the controller...&lt;/p&gt;&#10; &lt;input ng-init=&quot;message=&#39;test&#39;&quot; ng-model=&quot;message&quot; &gt;&#10; &lt;button ng-click=&quot;callNotify(message);&quot;&gt;NOTIFY&lt;/button&gt;&#10; &lt;p&gt;(you have to click 3 times to see an alert)&lt;/p&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<div class="runnable-example-file"
name="script.js"
language="js"
type="js">
<pre><code>angular.&#10; module(&#39;myServiceModule&#39;, []).&#10; controller(&#39;MyController&#39;, [&#39;$scope&#39;,&#39;notify&#39;, function ($scope, notify) {&#10; $scope.callNotify = function(msg) {&#10; notify(msg);&#10; };&#10; }]).&#10; factory(&#39;notify&#39;, [&#39;$window&#39;, function(win) {&#10; var msgs = [];&#10; return function(msg) {&#10; msgs.push(msg);&#10; if (msgs.length == 3) {&#10; win.alert(msgs.join(&quot;\n&quot;));&#10; msgs = [];&#10; }&#10; };&#10; }]);</code></pre>
</div>
<div class="runnable-example-file"
name="protractor.js"
type="protractor"
language="js">
<pre><code>it(&#39;should test service&#39;, function() {&#10; expect(element(by.id(&#39;simple&#39;)).element(by.model(&#39;message&#39;)).getAttribute(&#39;value&#39;))&#10; .toEqual(&#39;test&#39;);&#10;});</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-example108/index.html" name="example-example108"></iframe>
</div>
</div>
</p>
<div class="alert alert-info">
<strong>Note:</strong> Angular uses
<a href="http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter-injection/"><strong>constructor injection</strong></a>.
</div>
<h3 id="explicit-dependency-injection">Explicit Dependency Injection</h3>
<p>A component should explicitly define its dependencies using one of the <a href="guide/di">injection</a>
annotation methods:</p>
<ol>
<li><p>Inline array injection annotation (preferred):</p>
<pre><code class="lang-js">myModule.controller(&#39;MyController&#39;, [&#39;$location&#39;, function($location) { ... }]);</code></pre>
</li>
<li><p><code>$inject</code> property:</p>
<pre><code class="lang-js">var MyController = function($location) { ... };
MyController.$inject = [&#39;$location&#39;];
myModule.controller(&#39;MyController&#39;, MyController);</code></pre>
</li>
</ol>
<div class="alert alert-success">
<strong>Best Practice:</strong> Use the array annotation shown above.
</div>
<h3 id="implicit-dependency-injection">Implicit Dependency Injection</h3>
<p>Even if you don&#39;t annotate your dependencies, Angular&#39;s DI can determine the dependency from the
name of the parameter. Let&#39;s rewrite the above example to show the use of this implicit dependency
injection of <code>$window</code>, <code>$scope</code>, and our <code>notify</code> service:</p>
<p>
<div>
<a ng-href="http://plnkr.co/edit/ngdoc:example-example109@{{docsVersion}}?p=preview" class="btn pull-right" target="_blank">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="examples/example-example109"
module="myServiceModuleDI">
<div class="runnable-example-file"
name="index.html"
language="html"
type="html">
<pre><code>&lt;div id=&quot;implicit&quot; ng-controller=&quot;MyController&quot;&gt;&#10; &lt;p&gt;Let&#39;s try the notify service, that is implicitly injected into the controller...&lt;/p&gt;&#10; &lt;input ng-init=&quot;message=&#39;test&#39;&quot; ng-model=&quot;message&quot;&gt;&#10; &lt;button ng-click=&quot;callNotify(message);&quot;&gt;NOTIFY&lt;/button&gt;&#10; &lt;p&gt;(you have to click 3 times to see an alert)&lt;/p&gt;&#10;&lt;/div&gt;</code></pre>
</div>
<div class="runnable-example-file"
name="script.js"
language="js"
type="js">
<pre><code>angular.module(&#39;myServiceModuleDI&#39;, []).&#10; factory(&#39;notify&#39;, function($window) {&#10; var msgs = [];&#10; return function(msg) {&#10; msgs.push(msg);&#10; if (msgs.length == 3) {&#10; $window.alert(msgs.join(&quot;\n&quot;));&#10; msgs = [];&#10; }&#10; };&#10; }).&#10; controller(&#39;MyController&#39;, function($scope, notify) {&#10; $scope.callNotify = function(msg) {&#10; notify(msg);&#10; };&#10; });</code></pre>
</div>
<iframe class="runnable-example-frame" src="examples/example-example109/index.html" name="example-example109"></iframe>
</div>
</div>
</p>
<div class="alert alert-danger">
<strong>Careful:</strong> If you plan to <a href="http://en.wikipedia.org/wiki/Minification_(programming">minify</a> your code,
your variable names will get renamed unless you use one of the annotation techniques above.
</div>
<h2 id="creating-services">Creating Services</h2>
<p>Application developers are free to define their own services by registering the service&#39;s name and
<strong>service factory function</strong>, with an Angular module.</p>
<p>The <strong>service factory function</strong> generates the single object or function that represents the
service to the rest of the application. The object or function returned by the service is
injected into any component (controller, service, filter or directive) that specifies a dependency
on the service.</p>
<h3 id="registering-services">Registering Services</h3>
<p>Services are registered to modules via the <a href="api/ng/type/angular.Module">Module API</a>.
Typically you use the <a href="api/ng/function/angular.module">Module#factory</a> API to register a service:</p>
<pre><code class="lang-javascript">var myModule = angular.module(&#39;myModule&#39;, []);
myModule.factory(&#39;serviceId&#39;, function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});</code></pre>
<p>Note that you are not registering a <strong>service instance</strong>, but rather a <strong>factory function</strong> that
will create this instance when called.</p>
<h3 id="dependencies">Dependencies</h3>
<p>Services can have their own dependencies. Just like declaring dependencies in a controller, you
declare dependencies by specifying them in the service&#39;s factory function signature.</p>
<p>The example module below has two services, each with various dependencies:</p>
<pre><code class="lang-js">var batchModule = angular.module(&#39;batchModule&#39;, []);
/**
* The `batchLog` service allows for messages to be queued in memory and flushed
* to the console.log every 50 seconds.
*
* @param {*} message Message to be logged.
*/
batchModule.factory(&#39;batchLog&#39;, [&#39;$interval&#39;, &#39;$log&#39;, function($interval, $log) {
var messageQueue = [];
function log() {
if (messageQueue.length) {
$log.log(&#39;batchLog messages: &#39;, messageQueue);
messageQueue = [];
}
}
// start periodic checking
$interval(log, 50000);
return function(message) {
messageQueue.push(message);
}
}]);
/**
* `routeTemplateMonitor` monitors each `$route` change and logs the current
* template via the `batchLog` service.
*/
batchModule.factory(&#39;routeTemplateMonitor&#39;, [&#39;$route&#39;, &#39;batchLog&#39;, &#39;$rootScope&#39;,
function($route, batchLog, $rootScope) {
$rootScope.$on(&#39;$routeChangeSuccess&#39;, function() {
batchLog($route.current ? $route.current.template : null);
});
}]);</code></pre>
<p>In the example, note that:</p>
<ul>
<li>The <code>batchLog</code> service depends on the built-in <a href="api/ng/service/$interval"><code>$interval</code></a> and
<a href="api/ng/service/$log"><code>$log</code></a> services.</li>
<li>The <code>routeTemplateMonitor</code> service depends on the built-in <a href="api/ngRoute/service/$route"><code>$route</code></a>
service and our custom <code>batchLog</code> service.</li>
<li>Both services use the array notation to declare their dependencies.</li>
<li>The order of identifiers in the array is the same as the order of argument
names in the factory function.</li>
</ul>
<h3 id="registering-a-service-with-provide-">Registering a Service with <code>$provide</code></h3>
<p>You can also register services via the <a href="api/auto/object/$provide"><code>$provide</code></a> service inside of a
module&#39;s <code>config</code> function:</p>
<pre><code class="lang-javascript">angular.module(&#39;myModule&#39;, []).config(function($provide) {
$provide.factory(&#39;serviceId&#39;, function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
});</code></pre>
<p>This technique is often used in unit tests to mock out a service&#39;s dependencies.</p>
<h2 id="unit-testing">Unit Testing</h2>
<p>The following is a unit test for the <code>notify</code> service from the <a href="guide/services#creating-services">Creating Angular Services</a> example above. The unit test example uses a Jasmine spy (mock) instead
of a real browser alert.</p>
<pre><code class="lang-js">var mock, notify;
beforeEach(function() {
mock = {alert: jasmine.createSpy()};
module(function($provide) {
$provide.value(&#39;$window&#39;, mock);
});
inject(function($injector) {
notify = $injector.get(&#39;notify&#39;);
});
});
it(&#39;should not alert first two notifications&#39;, function() {
notify(&#39;one&#39;);
notify(&#39;two&#39;);
expect(mock.alert).not.toHaveBeenCalled();
});
it(&#39;should alert all after third notification&#39;, function() {
notify(&#39;one&#39;);
notify(&#39;two&#39;);
notify(&#39;three&#39;);
expect(mock.alert).toHaveBeenCalledWith(&quot;one\ntwo\nthree&quot;);
});
it(&#39;should clear messages after alert&#39;, function() {
notify(&#39;one&#39;);
notify(&#39;two&#39;);
notify(&#39;third&#39;);
notify(&#39;more&#39;);
notify(&#39;two&#39;);
notify(&#39;third&#39;);
expect(mock.alert.callCount).toEqual(2);
expect(mock.alert.mostRecentCall.args).toEqual([&quot;more\ntwo\nthird&quot;]);
});</code></pre>
<h2 id="related-topics">Related Topics</h2>
<ul>
<li><a href="guide/di">Dependency Injection in AngularJS</a></li>
</ul>
<h2 id="related-api">Related API</h2>
<ul>
<li><a href="./ng">Angular Service API</a></li>
<li><a href="api/ng/function/angular.injector">Injector API</a></li>
</ul>