Communicating with a Back-end Server
The unit test starts by the call to the $q.defer() method which returns a deferred
object. Conceptually it represents a task that will be completed (or will fail in the
future). The deferred object has two roles:
- It holds a promise object (in the promise property). Promises are
placeholders for the future results (success or failure) of a deferred task. - It exposes methods to trigger future task completion (resolve) or
failure (reject).
There are always two players in the Promise API: one that controls future task
execution (can invoke methods on the deferred object) and another one that depends
on the results of the future task execution (holds onto promised results).
The deferred object represents a task that will complete or fail in
the future. A promise object is a placeholder for the future results
of this task completion.
An entity that controls the future task (in our example it would be a restaurant)
exposes a promise object (pizzaOrderFulfillment.promise) to entities that
are interested in the result of the task. In our example, Pawel is interested in the
delivered order and can express his interest by registering callbacks on the promise
object. To register a callback the then(successCallBack, errorCallBack) method
is used. This method accepts callback functions that will be called with a future task
result (in case of success callback) or a failure reason (in case of error callback). The
error callback is optional and can be omitted. If the error callback is omitted and a
future task fails, this failure will be silently ignored.
To signal the future task completion the resolve method should be called on the
deferred object. The argument passed to the resolve method will be used as a value
provided to the success callback. After a success callback is called a future task is
completed and the promise is resolved (fulfilled). Similarly, the call to the reject
method will trigger the error callback invocation and promise rejection.
In the test example there is a mysterious call to the
$rootScope.$digest() method. In AngularJS results of promise
resolution (or rejection) are propagated as part of the $digest
cycle. You can refer to the Chapter 11, Writing Well-performing
AngularJS Web Applications, to learn more about AngularJS internals
and the $digest cycle.