Using Javascript Promises for Application Logic in an AngularJS Service
"A Promise is an object representing the eventual completion or failure of an asynchronous operation" - MDN Web Docs AngularJS has a  Promises/A+-compliant implementation of javascript promises in its $q service. For example, it uses this in the $http service to make asynchronous HTTP calls. The $q service is also available on its own and provides a convenient API for creating and consuming promises within an AngularJS application. This allows a developer to harness the power of promises for more than AJAX calls. We can use promises in all kinds of application specific contexts. This can help keep application code organized. The following example shows how the $q service can be used to separate application logic in an angular service and controller and keep the responsibility of each in the appropriate place. The full working example is available in this plunk.
The example divides 2 numbers and produces an error if attempting to divide by 0. Javascript returns infinity by default when trying to divide by 0 so my division service checks for this condition and returns an error when attempting to divide by 0. There is a simple template that contains 2 input fields, a button to divide them, and a placeholder for either the result of the division or an error message.
<label>Divide numbers:</label><input type="text" name="num1" ng-model="num1" id="num1" /> / <input type="text" name="num2" ng-model="num2" id="num2" /><button ng-click="divide()">Divide</button><p>{{answer}}</p>
The controller keeps track of num1 and num2 populated in the template and contains the divide() function called from the ng-click directive above. This function calls into the division service that actually performs the division and returns the quotient or an error. This is where things get interesting. The divide function in the service returns a promise that executes the division. The service checks for a divide by zero condition and only executes the division and resolves the promise if it’s not dividing by 0. If it is dividing by 0, the promise is rejected. Below is the divide function in the service.
_this.divide = function(num1, num2) {
     return $q(function(resolve, reject) {
          if (num2 != 0) {
               var result = num1/num2;
               resolve(result);
          }
          else {
               // Handle service level error handling here
               console.log("Invalid Division");
               reject("Divide by 0 error");
          }
     });
};
Because the function returns the promise itself, the controller can consume the promise from the service. This allows the controller to handle the success or failure of the promise in the appropriate context of the controller. In this case, if it’s successful set the answer property to the quotient and if it fails, set the answer property to an error message. Both of these are UI specific operations, therefore, both are appropriate to handle in the controller as highlighted below.
var dividePromise = divisionService.divide($scope.num1, $scope.num2);
dividePromise.then(function(quotient) {
     $scope.answer = "Successful Quotient = "+quotient;
}, function(failure) {
     // Handle UI level error handling here
     $scope.answer = failure;
     console.log("UI failure message");
});
The service can still handle the application logic and low level error handling while leaving the controller to fulfill its responsibility of managing the UI. Here is the promise that gets returned in the division service.
return $q(function(resolve, reject) {
     if (num2 != 0) {
          var result = num1/num2;
          resolve(result);
     }
     else {
          // Handle service level error handling here
          console.log("Invalid Division");
          reject("Divide by 0 error");
     }
}
In conclusion, promises are a great way to implement business logic in AngularJS services. They can keep controllers clean and focused on the UI, while allowing business logic to be organized through services based on specifics of the application.
    