Ben Nadel: Exploring Asynchronous Promise-Based Workflows In AngularJS

promises

by nickadeemus2002

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
<div ng-app="Demo" ng-controller="AppController">
     <h1>
        Exploring Asynchronous Promise-Based Workflows In AngularJS
    </h1>

    <p> <strong style="background-color: yellow ;">CAUTION</strong>: I wouldn't actually put so much workflow coordination on the <em>client-side</em>. Instead, I would put all of this behind a single asynchronous call to the server API. I am doing this here - in AngularJS - because the framework is <strong>JavaScript</strong> and has <strong>Promises</strong>. As such, it makes it really easy to test with; and, it makes it quite applicable to other asynchronous server-side technologies like Node.js.</p>
</div>

CSS

a[ng-click] {
    cursor: pointer;
    text-decoration: underline;
}
p.apply, p.digest {
    background-color: #FAFAFA;
    border: 3px solid #CCCCCC;
    cursor: default;
    float: left;
    height: 75px;
    line-height: 75px;
    text-align: center;
    width: 200px;
}
p.apply {
    margin-right: 30px;
}
p.apply.hot, p.digest.hot {
    background-color: #FFCCCC;
    border-color: #FF3399;
}
p.logging {
    clear: both;
}

JavaScript

// Create an application module for our demo.
var app = angular.module("Demo", []);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I control the root of the application.
app.controller(
    "AppController",
    function ($q, friendService, logService) {
        // As the asynchronous workflow executes, we'll want to keep track of
        // these values, externally, so that we don't have to constantly pass
        // them through each resolve and reject transformation.
        var friendOne = null;
        var friendTwo = null;

        // The goal here is to create a friendship. This requires us to:
        // --
        // 1. Get each friend in question.
        // 2. Apply superficial validation.
        // 3. Make sure a friendship doesn't already exist.
        // 4. Create the friendship.
        // --
          
        $q
          .all([  
               //Combines multiple promises into a single promise 
               //that is resolved when all of the input promises are resolved.
               //Returns a single promise that will be resolved 
               //with an array/hash of values, 
               friendService.getFriend(1),
               friendService.getFriend(2)
           ])
           .then(
               function handleFriendsResolve(friends) {                      
                  //get each friend from .all array                       
                  friendOne = friends.shift();
                  friendTwo = friends.shift();
                          
                  // Apply superficial validation.
                  //THIS WILL FALL UNTIL A FAIL RESOLUTION IS FOUND...
                  //WHICH MEANS REJECT WILL BE HANDLED @ .CATCH()
                  if (friendOne.likesMovies !== friendTwo.likesMovies) {
                      //one potential friend doesn't like movies
                      return ($q.reject("MovieIncompatibility"));
                  }
    ...