【问题标题】:Angular ng-repeat how to unwrap promise in template for each itemAngular ng-repeat如何在每个项目的模板中解开承诺
【发布时间】:2014-08-11 15:53:57
【问题描述】:

过去,函数返回的 Promise 曾经能够绑定到模板,并且当 Promise 被解析时,该值会在模板中自动更新。但是,我读到这种自动解包承诺不再存在。

我在下面提供了简化的代码,以说明我正在尝试做什么。我的控制器有一个包含对象的 dataArray。每个对象都包含一个 id 字段。控制器有一个函数,它接受 id 并返回一些数据的承诺。在模板中,我使用 ng-repeat 循环遍历 dataArray 中的每个对象(obj),并且我想绑定到 getData 为每个 obj 返回的 promise 的已解析值。然而,当我这样做时,我得到“10 $digest() 迭代达到。中止!”我读过的错误是由于缺少承诺展开,承诺不再绑定到模板。

控制器:

myApp.controller('myCtrl', function($scope, dataStore) {

  $scope.someDataArray = dataArray;  // an array of objects

  // returns a promise to provide data for the supplied id
  $scope.getData = dataStore.getData(id); 


})

模板:

<div>
  <table>
    <thead>
        ....
    </thead>
    <tbody>
      <tr ng-repeat="obj in dataArray">
        <td>{{obj.item1}}</td>
        <td>{{getData(obj.id)}}</td>
      </tr>
    </tbody>
  <table>
<div>

有没有人有一个好的方法可以将 ng-repeat 中的值数组中的值传递给返回 Promise 的函数,以便当 Promise 解决时,模板的每个表格单元格中的值都会更新?

我知道,如果我对单个值执行此操作,我可以为作用域上的值创建一个变量,并使用 promise 的 then() 函数来设置该值。模板将绑定到该值。但是,由于我使用的是 ng-repeat,因此 dataArray 中的每个 obj.id 都会有单独的函数调用。

【问题讨论】:

  • 我假设dataStore.getData 发出了某种异步请求——你为什么要做多个这样的请求?如果您必须获得 100 件物品,那么您将提出 100 个请求,而一次获得 100 件物品更有意义。
  • dataStore.getData 首先检查本地缓存,如果数据不存在,则会向服务器发出异步请求。拨打一个电话或多个电话都是可行的选择。

标签: angularjs


【解决方案1】:

嗯,我个人认为从视图中调用不是一个好习惯。

我会在视图中将事物分开,绑定到将由已解决的承诺填充的属性:

<div>
  <table>
    <thead>
        ....
    </thead>
    <tbody>
      <tr ng-repeat="obj in dataArray">
        <td>{{obj.item1}}</td>
        <td>{{obj.data)}}</td>
      </tr>
    </tbody>
  <table>
<div>

在我的控制器上,我会为数组的每个项目调用 getData(),为了让它变得更好,我会使用手表,所以每次我的数组更新时,我都会确保调用getData() 被执行

myApp.controller('myCtrl', function($scope, dataStore) {

   $scope.$watch('someDataArray ', function(newArray) {
      for(var i=0; i<newArray.length; i++){
          populateData(newArray[i]);
      }
   });

   var populateData = function(obj){
      dataStore.getData(obj.id).then(function(value){
          obj.data = value;
      });
   }

   $scope.someDataArray = dataArray;  // an array of objects

});

我还没有对此进行测试,但这是一般的想法。希望对您有所帮助。

【讨论】:

  • 这行不通,当.then() 被调用时,i 将始终等于newArray.length
  • 你说得对,我匆忙中忽略了这一点,我要编辑答案来修复它
【解决方案2】:

获取控制器中的数据:

$scope.fetchedData = [];
$q.all($scope.someDataArray.map(function(obj) {
    return dataStore.getData(obj.id);
}).then(function(array) {
    $scope.fetchedData = array;
});

并在视图中显示获取的数据:

<tr ng-repeat="obj in dataArray">
  <td>{{obj.item1}}</td>
  <td>{{ fetchedData[$index] }}</td>
</tr>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    相关资源
    最近更新 更多