AngularJS - 双向绑定承诺 - 处理拒绝

5
我已经深刻地认识到,当你双向绑定一个 promise 时,Angular 会为你解析该 promise 并绑定实际的 promise。 那么我的问题是,如何处理被拒绝的 promise 呢?
我的特殊情况是,我有一个指令,它双向绑定了来自控制器的 promise。我的控制器希望指令处理该 promise 的拒绝,因为错误需要在 DOM 上显示。
在我的指令中,我期望我的绑定变量是一个 promise,但是我得到的是该 promise 的解析值。这很让人恼火,但并不可怕。
问题在于,当 promise 被拒绝时,指令无法知道。
请参见此 plunker 作为示例:

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

我该如何在指令中处理Promise拒绝?

谢谢, Roy


作为解决方法,我在控制器中捕获了被拒绝的 Promise,将其包装成 Error 类型的值,并将 Promise 作为“成功”返回。这并不是很优雅。 - Roy Truelove
2个回答

1
成功和错误的回调可以使用&作为参数传递。
在这个选项中,控制器负责将回调函数添加到.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:plunkr}}


1
我有三个建议,虽然都不完美,但它们都能起作用:
  1. 创建一个getter方法,返回promise,并使用&将该方法绑定到指令上

  2. 绑定deferred对象而不是promise(丑陋)

  3. 当promise解决/被拒绝时广播一个事件

我已经创建了一个包含所有建议的plunker: http://plnkr.co/edit/jsA0PwpQm0xycLclkBU3?p=preview

  • 控制器:
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)
});
  • 标记语言:
<div promise-test deferred="deferred" get-promise='getPromise()' ></div>
  • 指令:
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          
        }
      })
    }
  }
})

谢谢,我会测试这个并回复你。 - Roy Truelove

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接