Angularjs承诺在1.2中不绑定模板

Pab*_*blo 35 angularjs

升级到1.2后,我的服务返回的承诺表现不同......简单的服务myDates:

getDates: function () {
           var deferred = $q.defer();

            $http.get(aGoodURL).
                 success(function (data, status, headers, config) {
                     deferred.resolve(data);  // we get to here fine.
            })......
Run Code Online (Sandbox Code Playgroud)

在早期版本中,我可以在我的控制器中执行:

$scope.theDates = myDates.getDates();
Run Code Online (Sandbox Code Playgroud)

并且从getDates返回的promise可以直接绑定到Select元素.现在这不起作用,我被迫在我的控制器中提供回调或数据不会绑定:

$scope.theDates = matchDates.getDates();
$scope.theDates.then(function (data) {
      $scope.theDates = data;  // this wasn't necessary in the past
Run Code Online (Sandbox Code Playgroud)

文档仍然说:

$ q promises被临界引擎识别为angular,这意味着在模板中,您可以将附加到范围的promise视为结果值.

他们(承诺)在Angular的旧版本中工作,但是在我所有的简单服务中,1.2 RC3自动绑定都失败了....任何关于我可能做错的想法.

Nen*_*nad 41

1.2.0-rc3有变化,包括你提到的一个:

AngularJS 1.2.0-rc3 ferocious-twitch修复了$ compile和$ animate中的一些高优先级问题,并为1.2铺平了道路.此版本还引入了一些重要的重大更改,在某些情况下可能会破坏您的指令和模板.请务必阅读更改日志以了解这些更改,并了解如何在需要时迁移代码.有关此版本中的完整详细信息,请参阅更改日志.

更改日志中有说明:

$解析:

  • 由于5dc35b52,$ parse和模板一般不会自动解包承诺.此功能已被弃用,如果绝对需要,可以在过渡期间通过$parseProvider.unwrapPromises(true)api 重新启用.
  • 由于b6a37d11,在rc.2中添加了一个功能,如果值是promises(如果启用了promise unwrapping,请参见上一点),则会从函数中解包返回值,由于打破了流行的使用模式而被还原.

  • 谢谢......至少这次不是我. (5认同)
  • 我无法理解为什么他们使用不稳定的分支,同时打破所谓的冻结释放候选人的一切...... (3认同)

Pet*_*ens 22

正如@Nenad所述,承诺不再自动解除引用.这是我见过的最离奇的决定之一,因为它默默地删除了我依赖的功能(这对我来说是一个独特的角度卖点,少即是多).因此我花了很多时间才弄明白这一点.特别是因为$ resource框架似乎仍然可以正常工作.除此之外,这也是一个候选版本.如果他们真的不得不弃用这个(这些论点听起来非常虚弱),他们至少可以给出一个宽限期,在他们默默关闭它之前会有警告.虽然通常对角度印象非常深刻,但这是一个很大的减号.如果这实际上将被恢复,我不会感到惊讶,尽管到目前为止似乎没有相对较少的抗议.

无论如何.有什么解决方案?

  • 始终使用then(),并在then方法中指定$ scope

    function Ctrl($scope) {
       foo().then( function(d) { $scope.d = d; });
    )
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过展开函数调用该值.此函数返回promise中的字段,并通过then方法设置此字段.因此,只要承诺未得到解决,它就不会被定义.

    $rootScope.unwrap = function (v) {
      if (v && v.then) {
        var p = v;
        if (!('$$v' in v)) {
          p.$$v = undefined;
          p.then(function(val) { p.$$v = val; });
        }
        v = v.$$v;
      }
      return v;
    };
    
    Run Code Online (Sandbox Code Playgroud)

    您现在可以调用它:

    Hello {{ unwrap(world) }}.
    
    Run Code Online (Sandbox Code Playgroud)

    这是来自http://plnkr.co/edit/Fn7z3g?p=preview,它没有与之关联的名称.

  • 设置$parseProvider.unwrapPromises(true)并使用您可以关闭的消息,$parseProvider.logPromiseWarnings(false)但最好注意他们可能会删除以下版本中的功能.

叹了口气,40年来,Smalltalk become发出了允许您切换对象引用的消息.承诺,因为他们本来可以......

更新:

在更改我的应用程序后,我发现了一个非常好用的一般模式.

假设我需要对象'x',并且有一些方法可以远程获取此对象.然后我将首先检查缓存中的'x'.如果有物体,我会把它归还.如果不存在这样的对象,我创建一个实际的空对象.不幸的是,这需要您知道这是一个数组还是一个哈希/对象.我将此对象放在缓存中,以便将来的调用可以使用它.然后我启动远程调用,在回调中,我复制从创建的对象中的远程系统获得的数据.缓存确保重复调用get方法不会为同一对象创建大量远程调用.

 function getX() {
   var x = cache.get('x');
   if ( x == undefined) {
      cache.put('x', x={});
      remote.getX().then( function(d) { angular.copy(d,x); } );
   }
   return x;
 }
Run Code Online (Sandbox Code Playgroud)

另一种方法是为get方法提供对象的目标:

 function getX(scope,name) {
   remote.getX().then( function(d) { 
       scope[name] = d;
   } );
 }       
Run Code Online (Sandbox Code Playgroud)