<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@*" data-semver="1.2.4" src="http://code.angularjs.org/1.2.4/angular.js"></script>
    <script data-require="datejs@*" data-semver="0.1.0" src="//cdnjs.cloudflare.com/ajax/libs/datejs/1.0/date.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="AppCtrl">
    <h1>{{title}}</h1>

  
  Val A = {{valA}}    <br />

  Val B = {{valB}}    <br />

  Val C = {{valC}}    <br />
    <ul>
      <li ng-repeat="line in log">{{line}}</li>
    </ul>
  </body>

</html>
// Code goes here

angular.module('app', []).controller('AppCtrl', function($scope, $q, $timeout) {
  var delay = 1000,
      throwStartA = false,
      throwDoneA = true,
      throwStartB = false,
      throwDoneB = false,
      recoverAtB = false,
      propagateAtB = false;
      
  $scope.title = "Promises, Promises!";
  $scope.log = [];
  
  function log(value){
    $scope.log.push(new Date().toString('mm:ss') + ' - ' + value);
  }
  
  function GetValueA() {
    var def = $q.defer();

    log('Start A');
    if (throwStartA) throw new Error('Start A');
    
    $timeout(function() {
      log('Done A');
      
      try {
        if (throwDoneA) throw new Error('Done A');
        def.resolve('Value A');
      }
      catch(e) {
        def.reject(e);
      }
      
    }, delay);

    return def.promise;
  }

  function GetValueB() {
    var def = $q.defer();

    log('Start B');
    if (throwStartB) throw new Error('Start B');
    
    $timeout(function() {
      log('Done B');
      
      try {
        if (throwDoneB) throw new Error('Done B');
        def.resolve('Value B');
      }
      catch(e) {
        def.reject(e);
      }
    }, delay * 2);

    return def.promise;
  }

  function GetValueC() {
    var def = $q.defer();

    log('Start C');

    $timeout(function() {
      log('Done C');
      def.resolve('Value C');
    }, delay * 3);

    return def.promise;
  }

  // when() returns a promise that is already resolved with a value of 'undefined'.
  $q.when()
    .then(function(){
      // Now GetValueA() is inside a try/catch block because we called it inside then().
      return GetValueA();
    })
    .then(function(val){ // success callback for promise returned by GetValueA
      $scope.valA = val;
      return GetValueB();
    })
    .then(function(val){ // success callback for promise returned by GetValueB
      $scope.valB = val;
      return GetValueC();
    }, function(err){    // error callback for promise returned by GetValueB
      log('Catch B - ' + err);
      
      if (recoverAtB) {
        return 'Recovered Value';  
      }
      else if (propagateAtB) {
        return $q.reject(err);
      }
    })
    .then(function(val){ // then for promise returned by GetValueC
      $scope.valC = val;
    })
    .catch(function(err){
      log('Catch End - ' + err);
    });

});
/* Styles go here */