ng-repeat with directive:如何在数组更改后销毁重复的项目?

时间:2016-11-15 16:32:43

标签: javascript angularjs

我有一个角度js应用程序,它使用带有这样的指令的ng-repeat:

<div data-ng-repeat="n in items">
   <div data-my-directive
        item="n"></div>
</div>

其中items是一个带整数的数组。

根据用户的操作,items数组可以完全销毁,并使用新的整数重新生成。

第一次,可能是[1,2,4,9] 接下来可能是[1,3,6,7] 例如。这取决于一些用户选择。

指令my-directive将在服务器端执行一些业务逻辑,因此它会在加载后立即调用服务器。然后在结果返回后,它向用户显示一个很好的表。

问题是有些用户不会等到一切都很好并加载并切换视图(这意味着数组会发生变化)。在这种情况下,我看到对服务器的调用仍在执行,并且结果函数仍然被调用,即使指令本身已被销毁,因为ngRepeat已经反弹并且所有指令都被重新制作。

例如:

$http.get(service.url + '/filters').success(function(result) {
    alert(result);
 });

这将显示所有警报,甚至是不再显示在页面上的指令。 这带来了一些问题。我可以在数组更改时删除重复中的指令或类似的东西,以确保在不再存在的指令中不执行任何逻辑(或者不再在页面上显示)? 或者您对如何最好地解决这个问题有其他想法?

理想情况下,指令应该在ng-repeat自身反弹后消失,因此一旦数据从服务器返回,就不会执行任何逻辑。

3 个答案:

答案 0 :(得分:1)

当用户更改参数时,您可以取消正在运行的请求并开始新的请求。

In this Scott Allen's blog post你可以找到有关这项工作的详细解释。

您开始使用您将调用的方法创建服务或工厂:

var getData = function(){
    var canceller = $q.defer();

    var cancel = function(reason){
        canceller.resolve(reason);
    };

    var promise =
        $http.get(service.url + '/filters', { timeout: canceller.promise})
            .then(function(response){
               return response.data;
            });

    return {
        promise: promise,
        cancel: cancel
    };
};

然后你这样称呼它:

var request = service.getData();
$scope.requests.push(request);
request.promise.then(function(movie){
    $scope.movies.push(movie);
    clearRequest(request);
}, function(reason){
    console.log(reason);
});

然后提供一个取消请求的方法:

$scope.cancel = function(){
    var request = // retrieve the correct request from the requests array        
    request.cancel("User cancelled");
    // Remove the request from the array
};

答案 1 :(得分:0)

所以我对你的问题有一些想法。

首先你可以使用ng-cloak,它可以防止浏览器在你的应用程序加载时以原始(未编译)形式短暂显示Angular html模板。如果我希望用户等到所有数据都返回到查看页面,我发现这非常有用。离。

<div id="template1" ng-cloak>{{ 'hello' }}</div>

第二次你可以尝试解决问题。解析包含一个或多个必须在路由更改之前成功解析的promise。这意味着您可以在实际更改路径之前等待数据可用。

$routeProvider
    .when("/news", {
        templateUrl: "newsView.html",
        controller: "newsController",
        resolve: {
            message: function(messageService){
                return messageService.getMessage();
        }
    }
})

答案 2 :(得分:0)

该指令需要使用$destroy事件来取消正在进行的操作。

app.directive("myDirective", function() {
    return {
        controller: function($scope, $http, $q) {
            var canceller = $q.defer();
            var cancel = function(reason){
                canceller.resolve(reason);
            };

            $http.get(url, { timeout: canceller.promise})
               .then(function(response){
                   $scope.data = response.data;
               });

           $scope.$on('$destroy', function () {
               cancel("Scope destroyed");
           });
       }
    }
});

ng-repeat删除某个项目时,它会破坏该项目的范围。使用$destroy事件取消正在进行的异步操作。

来自文档:

  

$destroy()方法通常由ngRepeat等指令用于管理循环的展开。

     

在销毁范围之前,会在此范围内广播$destroy个事件。应用程序代码可以注册一个$destroy事件处理程序,使其有机会执行任何必要的清理。

- AngularJS $rootScope.scope API Reference -- $destroy