AngularJS - two-way binding promises - failover

I found that when you do two-way binding to a promise, angular solves the promise for you and binds the actual promise . My question is, how would you handle a rejected promise?

My private business is that I have a directive in which I associate a bilateral agreement with my controller. My controller expects the directive to abandon this promise, since the error should map to the DOM.

In my directive, I would expect my bound variable to be a promise, but instead I get the resolved value of that promise. Annoying, but not scary.

The problem is , when this promise is rejected, the directive has no way to find out .

See this plunker for an example:

http://plnkr.co/edit/m0cOqFhx6TNrDxTbr9Qx?p=preview

How can I handle a proposal rejection in my directive?

Thanks Roy

+5
source share
2 answers

I have three suggestions - none of them are perfect, but they all work:

  • Create a getter method that returns a promise and bind this method to a directive using &

  • Snap deferred object instead of promise (ugly)

  • Passing an event when a promise is resolved / rejected

I created a plunker with all the suggestions: http://plnkr.co/edit/jsA0PwpQm0xycLclkBU3?p=preview

  • Controller:
app.controller('MainCtrl', function($scope,$q,$timeout) {
  var deferred = $q.defer();

  $scope.promise = deferred.promise;
  $scope.deferred = deferred;

  $scope.getPromise = function(){
    return deferred.promise;
  }

  $scope.promise.then(function(msg){
    $scope.$broadcast('promiseThen',{rejected:false,msg:msg});
  },function(msg){
    $scope.$broadcast('promiseThen',{rejected:true,msg:msg});
  });

  $timeout(function(){deferred.reject('No reason...');},1500)
});
  • Markup:
<div promise-test deferred="deferred" get-promise='getPromise()' ></div>
  • Directive
app.directive('promiseTest',function(){
  return {
    template:'<div>m1: {{m1}}<br>m2: {{m2}}<br>m3: {{m3}}</div>',
    scope:{getPromise:'&',deferred:'='}
    ,link:function(scope,el,attrs){

      scope.m1 = scope.m2 = scope.m3 = 'Waiting...';

      scope.getPromise().then(function(msg){
        scope.m1 = 'Resolve getPromise: '+msg;
      },function(msg){
        scope.m1 = 'Reject getPromise: '+msg;
      })

      scope.deferred.promise.then(function(msg){
        scope.m2 = 'Resolved deferred.promise: '+msg
      },function(msg){
        scope.m2 = 'Rejected deferred.promise: '+msg
      });

      scope.$on('promiseThen',function(ev,val){
        if(val.rejected){
          scope.m3 = 'Rejected promiseThen: '+val.msg
        }else{
          scope.m3 = 'Resolved promiseThen: '+val.msg          
        }
      })
    }
  }
})
+1
source

Successful and error callbacks can be passed as parameters using &.

.then.

app.controller('MainCtrl', function($scope,$q,$timeout) {
  var deferred = $q.defer();

  $scope.register = function(callback, errback) {
    deferred.promise.then(callback, errback);
  }

  $timeout(function(){deferred.reject('No reason...');},1500)
});

app.directive('promiseTest',function(){
  return {
    template:'<div>m1: {{m1}}',
    scope:{register:'&'},
    link:function(scope,el,attrs){

      scope.m1 = 'Waiting...';

      scope.register({
        success: function(msg){
          scope.m1 = 'Resolve getPromise: '+msg;
        },
        errback: function(msg){
          scope.m1 = 'Reject getPromise: '+msg;
        }
      });
    }
  }
})

HTML

<div promise-test register='register(success, errback)' ></div>

plunkr

+1

All Articles