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

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angularjs@1" data-semver="1.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
    <script src="script.js"></script>
  </head>

  <body ng-controller="MainCtrl">
      <h3>Succeeded</h3>
    <div ng-repeat="line in results">
      
      <p ng-if="line.succeeded">{{line.msg}}</p>
    </div>
      <h3>Failed</h3>
    
        <div ng-repeat="line in results">
    <p ng-if="!line.succeeded">{{line.msg}}</p>
    </div>

  </body>

</html>
var app = angular.module('plunker', []);
app.config(function($provide) {
  $provide.decorator("$q", function($delegate) {
    //Helper method copied from q.js.
    var isPromiseLike = function(obj) {
      return obj && angular.isFunction(obj.then);
    }

    /*
     * Adapted from the post and comments at http://www.codeducky.org/q-serial/
     * @description Execute a collection of tasks serially.  A task is a function that returns a promise
     *
     * @param {Array.<Function>|Object.<Function>} tasks An array or hash of tasks.  A tasks is a function
     *   that returns a promise.  You can also provide a collection of objects with a success tasks, failure task, and/or notify function
     * @returns {Promise} Returns a single promise that will be resolved or rejected when the last task
     *   has been resolved or rejected.
     */
    function serial(tasks) {
      //Fake a “previous task” for our initial iteration
      var prevPromise;
      var error = new Error();
      var results = [];

      var lastTask = function() {
        var endPromise = $delegate.defer();
        endPromise.resolve(results);
        return endPromise.promise;
      }
      tasks = tasks.concat(lastTask);

      angular.forEach(tasks, function(task, key) {

        var success = task.success || task;
        var fail = task.fail;
        var notify = task.notify;
        var nextPromise;

        //First task
        if (!prevPromise) {
          nextPromise = success();
          if (!isPromiseLike(nextPromise)) {
            error.message = "Task " + key + " did not return a promise.";
            throw error;
          }
        } else {
          //Wait until the previous promise has resolved or rejected to execute the next task
          nextPromise = prevPromise.then(
            /*success*/
            function(result) {
              results.push(result);
              if (!success) return results;
              var ret = success(result);
              if (!isPromiseLike(ret)) {
                error.message = "Task " + key + " did not return a promise.";
                throw error;
              }
              return ret;
            },
            /*failure*/
            function(reason) {
              if (!fail) {
                return $delegate.reject(reason);
              }
              var ret = fail(reason);
              if (!isPromiseLike(ret)) {
                error.message = "Fail for task " + key + " did not return a promise.";
                throw error;
              }
              return ret;
            },
            notify);
        }
        prevPromise = nextPromise;
      });

      return prevPromise || $delegate.when();
    }

    $delegate.serial = serial;
    return $delegate;
  });
});
app.controller('MainCtrl', function($scope, $q) {
  $scope.results = [];
  var ctrl = this;
  ctrl.intermediateResults = [];

  function getMyPromise(i) {
    return function() {
    var response = {
      succeeded: false,
      msg: ''
    };

    var deferred = $q.defer();
    /* The problem with $q.all() is that it runs things in parallel. We want serial */
    // to simulate error, every 7th request fails
    if (i % 7 === 0) {

      response.succeeded = false;
      response.msg = 'error ' + i;
      deferred.resolve(response);
    } else {
      response.succeeded = true;
      response.msg = 'hello ' + i;

      deferred.resolve(response);
    }
    return deferred.promise;
    }
  }

  var promises = [];
  for (var i = 1; i <= 15; i++) {
    console.log("added promise");
    promises.push(getMyPromise(i));
  }

  $q.serial(promises).then(function(response) {
      console.log("RESULTS:" + JSON.stringify(response));
      $scope.results = response;
    })
    .catch(function(error) {
      console.log("ERROR:" + error);
    });
});
/* Styles go here */