Promises explained

by riddla

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<div ng-app="promisesApp">
    <div ng-controller="PromisesCtrl">
        <h2>Hi, I'm a promise and my state is <span ng-class="{'text-muted': promiseStateIs('undefined'), 'text-info': promiseStateIs('pending')}">{{state()}}</span>.</h2>
        <div class="progress">
            <div class="progress-bar" role="progressbar" aria-valuenow="00" aria-valuemin="0" aria-valuemax="100" ng-style="myStyle"></div>
        </div>
        
        <dl class="dl-horizontal">
            <dt ng-show="promiseStateIs('undefined')"><pre>{{dumbMethodCode('startPromise')}}</pre></dt>
            <dd><button class="btn btn-default" ng-click="startPromise()" ng-disabled="promiseIsStarted()">Start Promise</button></dd>
        </dl>
        <dl class="dl-horizontal" ng-hide="promiseStateIs('undefined')">
            <dt>
                <pre>dfd progress = {{progress}}</pre>
                <blockquote>The deferred.notify() Deferred method, calls any progressCallbacks on a Deferred object, optionally passing arguments.</blockquote>
                <pre>{{dumbMethodCode('progressPromise')}}</pre>
                            
                <pre>{{dumbMethodCode('bindProgress')}}</pre>
            </dt>
            <dd><button class="btn btn-default" ng-click="progressPromise()">Progress Promise</button></dd>
        </dl>
    </div>
</div>

CSS

.form-control { width:20%; }

JavaScript

var promisesApp = angular.module('promisesApp', []);

promisesApp.controller('PromisesCtrl', function PromisesCtrl($scope) {
    $scope.progress = 0;

    $scope.myStyle = {};
    
    $scope.foo = function() {
        return true;
    };

    $scope.dumbMethodCode = function(method) {
        return $scope[method].toString();
    };

    $scope.promiseState = function() {
        return $scope.myPromise.state();
    };

    $scope.promiseStateIs = function(what) {
        if (typeof $scope.myPromise === 'undefined') {
             return what === 'undefined';   
        }
        return $scope.myPromise.state() === what;
    };

    $scope.promiseIsUndefined = function() {
        return typeof $scope.myPromise === 'undefined';
    };

    $scope.startPromise = function() {
        $scope.myPromise = $.Deferred();
        
        $scope.bindProgress();
    };
     $scope.promiseIsStarted = function() {
        return ! $scope.promiseStateIs('undefined');
    };
    
    $scope.bindProgress = function() {
        $scope.myPromise.progress(function(prog) {
            $scope.myStyle = { width: $scope.progress + "%" };
        });
    };
    
    $scope.progressPromise = function() {
        $scope.progress += 10;
        $scope.myPromise.notify($scope.progress);
    };

    $scope.state = function() {
        return $scope.myPromise.state();
    };

    $scope.resolveDfd = function() {
        $scope.dfd.resolve();
    };

    $scope.progressDfd = function() {
        $scope.progress += 10;
    };
});