2013-07-05 6 views
7

J'essaie de trouver un moyen de charger de grandes quantités de données (plus de 1000 lignes) dans une page, sans pagination. Le premier obstacle dans c'était d'interroger la base de données en morceaux bouchées parallèles, que je l'ai fait avec l'aide de la solution à How to make sequentially Rest webservices calls with AngularJS?Chargement de grands ensembles de données avec AngularJS

Je suis en cours d'exécution en deux problèmes mais ce que j'ai mis en place:

  1. Chaque objet retourné est passé dans un tableau qui est lui-même retourné comme le tableau qu'Angular utilise pour se lier. ie [[{clé: valeur, clé: valeur, clé: valeur}, {clé: valeur, clé: valeur, clé: valeur}], [{clé: valeur, clé: valeur, clé: valeur}, {clé: value, key: value, key: value}]] En tant que tel, je ne peux pas utiliser ng-repeat = "item dans les données" car les données sont un tableau de tableaux. Faire "item in data [0]" rend l'objet disponible. La concaténation semble être la réponse, mais je n'ai pas réussi à trouver un moyen de la faire fonctionner. Je fais plusieurs demandes à la base de données et chaque demande est renvoyée correctement mais la page ne restitue pas jusqu'à ce que toutes les demandes soient terminées - ce qui annule complètement le point de faire plusieurs demandes en premier lieu.

Alors en regardant mon code, comment puis-je le réécrire pour résoudre ces deux problèmes? Alors que les données sont renvoyées en tant qu'un tableau et que les données sont rendues chaque fois qu'une requête est terminée?

app.factory('ScanService', function($http, $q) { 
    function fetchOne(stepCount) { 
    return $http({ 
     method: 'GET', 
     url: '/index.php/scans', 
     params: {step:stepCount} 
    }) 
    .then(function onSuccess(response) { 
     return response.data; 
    } 
    return { 
     fetchAll: function(steps) { 
     var scans = []; 
     for (var i = 1; i <= steps; i++) { 
      scans.push(fetchOne(i)); 
     } 
     return $q.all(scans); 
     } 
    }; 
}); 

app.controller.ScanCtrl = function($scope, $q, ScanService) { 
    $scope.scans = ScanService.fetchAll(10); 
}; 

Suivre jusqu'à

Je dois ajouter que j'ai réussi à obtenir ce travail basé sur la solution ci-dessous et un angular.forEach(). Je ne peux pas suggérer à quiconque travaillant avec "big data" de suivre cette route. À environ 1000 lignes, le navigateur a été submergé et a commencé à ralentir considérablement. Essayer de filtrer avec angular.filter a également connu un retard significatif jusqu'à ce que les résultats soient réduits. D'un autre côté, quelques centaines de lignes fonctionnaient de manière respectable et permettaient le filtrage natif, ce qui était un objectif clé pour ma mise en œuvre.

+3

Qui, avec un esprit sain, veut regarder des milliers de lignes de données? – Bart

+0

@Bart Malheureusement, j'ai dû faire cela aussi. Certains analystes d'affaires sont à l'aise de travailler avec des milliers de lignes de données Excel et veulent une vue similaire sur le web. Bien que je suis entièrement d'accord avec eux, parfois vous devez faire ce que le client veut :( – Terry

+0

@Bart qui veut cliquer à travers 100 pages de 10 lignes chacun? Je suppose que c'est vraiment moi à la recherche de solutions alternatives au paradigme de pagination et de défilement infini ne résout pas le problème que je rencontre.L'intention générale est que vous chargez vos données et ensuite les filtrer dans Angular de sorte que vous ne seriez pas nécessairement à la recherche de 1000 lignes - mais vous pourriez si vous étiez fou. – iamsar

Répondre

6

Vous ne pouvez pas vraiment $ q.all les promesses ensemble (ce qui en fait une grande promesse qui réussit ou échoue ensemble) si vous voulez traiter chacun individuellement (afficher chacun individuellement).

Je voudrais pousser les choses que vous obtenez de nouveau dans le champ d'application dès que vous les obtenez. est un exemple ci-dessous:

function MyCtrl($scope, $timeout, $q) { 
     var fetchOne = function() { 
      var deferred = $q.defer(); 
      $timeout(function() { 
       deferred.resolve([random(), random() + 100, random() + 200]); 
      }, random() * 5000); 
      return deferred.promise; 
     }; 

     $scope.scans = []; 
     for (var i = 0; i < 2; i++) { 
      fetchOne().then(function(items) { 
       angular.forEach(items, function(item) { 
        $scope.scans.push(item); 
       }); 
      }); 
     }; 
    } 

est ici un violon montrant en action: http://jsfiddle.net/wWcvx/1/

Il y a un problème ici où l'ordre des articles sont basés sur le moment où ils ont été retournés, et non sur votre commande de demande initiale. Je vais vous laisser imaginer cela par vous-même.

+0

Merci pour la réponse. Il faudra quelques semaines avant que je sois de retour au bureau pour tester cela, mais j'ai hâte de le mettre à profit. La commande elle-même ne devrait en fait pas avoir d'importance. – iamsar

+2

Finalement, il a fallu donner un autre coup d'oeil. A travaillé magnifiquement. Beaucoup plus facile que j'ai d'abord essayé de le faire. Cette fonction 'angular.forEach' était la clé. – iamsar

Questions connexes