2014-08-29 53 views
7

我對Angular來說很新,所以也許我在問不可能,但無論如何,這是我的挑戰。在AngularJS中使用oboe.js流式傳輸JSON的解決方案?

由於我們的服務器無法對JSON數據進行分頁,因此我想將JSON流式傳輸並將其逐頁添加到控制器的模型中。用戶不必等待整個流加載,因此我刷新每個X(pagesize)記錄的視圖。

我發現瞭解析JSON流的oboe.js並將它添加到我的項目使用鮑爾。 (涼亭安裝雙簧管 - 保存)。

我想在流式傳輸過程中更新控制器型號。我沒有使用pomises的$ q實現,因爲只有一個.resolve(...)可能,並且我想要通過流加載多頁數據,因此需要在每個頁面中調用$ digest。這就是所謂的RESTful服務是/服務/任務/搜索

我創建了一個工廠,一個搜索功能,我從控制器內調用:

'use strict'; 

angular.module('myStreamingApp') 
    .factory('Stream', function() { 
     return { 
      search: function(schema, scope) { 
       var loaded = 0; 
       var pagesize = 100; 
       // JSON streaming parser oboe.js 
       oboe({ 
        url: '/service/' + schema + '/search' 
       }) 
         // process every node which has a schema 
         .node('{schema}', function(rec) { 
          // push the record to the model data 
          scope.data.push(rec); 
          loaded++; 
          // if there is another page received then refresh the view 
          if (loaded % pagesize === 0) { 
           scope.$digest(); 
          } 
         }) 
         .fail(function(err) { 
          console.log('streaming error' + err.thrown ? (err.thrown.message):''); 
         }) 
         .done(function() { 
          scope.$digest(); 
         }); 
      } 
     }; 
    }); 

我的控制器:

'use strict'; 
angular.module('myStreamingApp') 
    .controller('MyCtrl', function($scope, Stream) { 
     $scope.data = []; 
     Stream.search('tasks', $scope); 
    }); 

這一切接縫工作。不過一段時間後,系統變慢,並且在刷新瀏覽器後http呼叫不會終止。當加載的記錄太多時,瀏覽器(chrome)也會崩潰。 也許我在錯誤的軌道上,因爲將範圍傳遞給工廠搜索功能並不「感覺」正確,我懷疑在該範圍調用$摘要給我帶來麻煩。任何關於這個問題的想法都是受歡迎特別是如果你有一個關於在工廠(或服務)可能返回承諾的地方實施它的想法,並且我可以在控制器中使用

$scope.data = Stream.search('tasks'); 

回答

14

我進一步挖掘並提出了以下解決方案。它可以幫助某人:

工廠(名爲Stream)具有一個搜索功能,該功能爲Ajax請求和回調函數傳遞參數。該流將加載的每一頁數據都會調用該回調函數。回調函數通過deferred.promise調用,因此範圍可以隨每個頁面自動更新。爲了訪問搜索功能,我使用了一個服務(名爲Search),它最初返回一個空的數據。隨着流的發展,工廠將調用服務傳遞的回調函數,並將頁面添加到數據中。

我現在可以在控制器中調用搜索服務表單,並將返回值分配給作用域數據數組。

的服務和工廠:

'use strict'; 
angular.module('myStreamingApp') 
     .service('Search', function(Stream) { 
      return function(params) { 
       // initialize the data 
       var data = []; 
       // add the data page by page using a stream 
       Stream.search(params, function(page) { 
        // a page of records is received. 
        // add each record to the data 
        _.each(page, function(record) { 
         data.push(record); 
        }); 
       }); 
       return data; 
      }; 
     }) 
     .factory('Stream', function($q) { 
      return { 
       // the search function calls the oboe module to get the JSON data in a stream 
       search: function(params, callback) { 
        // the defer will be resolved immediately 
        var defer = $q.defer(); 
        var promise = defer.promise; 
        // counter for the received records 
        var counter = 0; 
        // I use an arbitrary page size. 
        var pagesize = 100; 
        // initialize the page of records 
        var page = []; 
        // call the oboe unction to start the stream 
        oboe({ 
         url: '/api/' + params.schema + '/search', 
         method: 'GET' 
        }) 
          // once the stream starts we can resolve the defer. 
          .start(function() { 
           defer.resolve(); 
          }) 
          // for every node containing an _id 
          .node('{_id}', function(node) { 
           // we push the node to the page 
           page.push(node); 
           counter++; 
           // if the pagesize is reached return the page using the promise 
           if (counter % pagesize === 0) { 
            promise.then(callback(page)); 
            // initialize the page 
            page = []; 
           } 
          }) 
          .done(function() { 
           // when the stream is done make surethe last page of nodes is returned 
           promise.then(callback(page)); 
          }); 
        return promise; 
       } 
      }; 
     }); 

現在我可以從控制器內調用該服務,並分配該服務的對範圍的響應:

$scope.mydata = Search({schema: 'tasks'}); 

更新2014年8月30日

我已經創建了一個帶有上述解決方案的angular-oboe模塊,它有點結構化。 https://github.com/RonB/angular-oboe