2013-09-22 38 views
5

Tôi đang viết một ứng dụng web nhỏ Angular và đã gặp sự cố khi tải dữ liệu. Tôi đang sử dụng Firebase làm nguồn dữ liệu và tìm thấy dự án AngularFire nghe hay. Tuy nhiên, tôi gặp sự cố khi kiểm soát cách dữ liệu đang được hiển thị.angularfireCollection: biết khi nào dữ liệu được tải đầy đủ

Lúc đầu, tôi đã cố gắng sử dụng đồng bộ ngầm thường xuyên bằng cách thực hiện:

angularFire(ref, $scope, 'items'); 

Nó hoạt động tốt và tất cả các dữ liệu được hiển thị khi tôi sử dụng mô hình $ items trong quan điểm của tôi. Tuy nhiên, khi dữ liệu đến từ nguồn dữ liệu Firebase, nó không được định dạng theo cách mà khung nhìn hỗ trợ, vì vậy tôi cần thực hiện một số thay đổi cấu trúc bổ sung cho dữ liệu trước khi dữ liệu được hiển thị. Vấn đề là, tôi sẽ không biết khi nào dữ liệu đã được tải đầy đủ. Tôi đã thử gán một đồng hồ $ cho $ item, nhưng nó được gọi là quá sớm.

Vì vậy, tôi chuyển vào và cố gắng sử dụng angularfireCollection thay vì:

$scope.items = angularFireCollection(new Firebase(url), optionalCallbackOnInitialLoad); 

Các tài liệu không phải là khá rõ ràng những gì mà "optionalCallbackOnInitialLoad" làm và khi nó được gọi, nhưng cố gắng để truy cập vào mục đầu tiên trong bộ sưu tập $ items sẽ ném một lỗi ("Uncaught TypeError: Không thể đọc thuộc tính '0' của undefined").

Tôi đã cố gắng thêm một nút và trong handler click của nút tôi đăng nội dung của mục đầu tiên trong $ items, và nó làm việc :

console.log($scope.items[0]); 

Có nó được! Đối tượng đầu tiên từ Firebase của tôi được hiển thị mà không có bất kỳ lỗi nào ... chỉ có vấn đề là tôi phải bấm vào một nút để đến đó.

Vì vậy, không ai biết làm thế nào tôi có thể biết khi tất cả các dữ liệu đã được nạp và sau đó gán nó vào một phạm vi biến $ sẽ được hiển thị theo quan điểm của tôi không? Hoặc là có một cách khác?

điều khiển của tôi:

app.controller('MyController', ['$scope', 'angularFireCollection', 
    function MyController($scope, angularFireCollection) { 
    $scope.start = function() 
    { 
     var ref = new Firebase('https://url.firebaseio.com/days'); 
     console.log("start"); 

     console.log("before load?"); 

     $scope.items = angularFireCollection(ref, function() 
     { 
      console.log("loaded?"); 
      console.log($scope.items[0]); //undefined 
     }); 

     console.log("start() out");  
    }; 

    $scope.start(); 

    //wait for changes 
    $scope.$watch('items', function() { 
     console.log("items watch"); 
     console.log($scope.items[0]); //undefined 
    }); 

    $scope.testData = function() 
    { 
     console.log($scope.items[0].properties); //not undefined 
    }; 
    } 
]); 

Quan điểm của tôi:

<button ng-click="testData()">Is the data loaded yet?</button> 

Cảm ơn trước!

+0

thử điều này: angularFireCollection (ref, function (data) { $ scope.items = dữ liệu; console.log ($ phạm vi. các mục [0]); }); –

Trả lời

2

So, does anyone know how I can know when all the data has been loaded and then assign it to a $scope variable to be displayed in my view? Or is there another way?

Hãy nhớ rằng tất cả cuộc gọi Firebase đều không đồng bộ. Nhiều vấn đề của bạn đang xảy ra vì bạn đang cố truy cập các phần tử chưa tồn tại. Lý do nút bấm hoạt động cho bạn là vì bạn đã bấm vào nút (và truy cập các phần tử) sau khi chúng đã được tải thành công.

Trong trường hợp optionalCallbackOnInitialLoad, đây là chức năng sẽ được thực hiện khi tải ban đầu của angularFireCollection hoàn tất. Như tên của nó, nó là tùy chọn, có nghĩa là bạn không phải cung cấp chức năng gọi lại nếu bạn không muốn.

Bạn có thể sử dụng tính năng này và chỉ định một chức năng được thực hiện sau khi được tải hoặc bạn có thể sử dụng lời hứa $q hoặc thư viện lời hứa khác theo ý thích của bạn. Tôi là một phần của chính mình với số điện thoại kriskowal's Q. Tôi khuyên bạn nên đọc một chút trên JavaScript không đồng bộ để bạn hiểu sâu hơn về một số vấn đề này.

Hãy cảnh giác rằng đây:

$scope.items = angularFireCollection(ref, function() 
     { 
      console.log("loaded?"); 
      console.log($scope.items[0]); //undefined 
     }); 

không xác định một cách chính xác một chức năng gọi lại, nhưng $scope.items không được giao cho đến khi sau bạn đã chạy callback. Vì vậy, nó vẫn sẽ không tồn tại.

Nếu bạn chỉ muốn nhìn thấy khi $scope.items đã được nạp, bạn có thể thử một cái gì đó như thế này:

$scope.$watch('items', function (items) { 
    console.log(items) 
}); 
+0

Xin chào và cảm ơn! Gọi lại không có một "kết quả" trong nó, nhưng nó không chứa dữ liệu của tôi vì vậy tôi không thực sự biết nó là gì. Bạn có muốn chia sẻ một ví dụ đơn giản về cách thực hiện lời hứa $ q ở đây không? Tôi đang gặp khó khăn trong việc hiểu cách sử dụng nó trong ngữ cảnh này. – iafiawik

+0

@iafiawik Nếu bạn chỉ muốn thực hiện việc này cho mục đích gỡ lỗi, bạn có thể sử dụng '$ scope. $ Watch' mà tôi đã hiển thị trong ví dụ nhanh ở trên ngay bây giờ. –

1

Trong dự án của tôi, tôi cần phải biết quá khi dữ liệu đã được nạp. Tôi đã sử dụng các phương pháp sau đây (bindings ngầm):

$scope.auctionsDiscoveryPromise = angularFire(firebaseReference.getInstance() + "/auctionlist", $scope, 'auctionlist', []); 

$scope.auctionsDiscoveryPromise.then(function() { 
    console.log("AuctionsDiscoverController auctionsDiscoveryPromise resolved"); 
    $timeout(function() { 
     $scope.$broadcast("AUCTION_INIT"); 
    }, 500); 

}, function() { 
    console.error("AuctionsDiscoverController auctionsDiscoveryPromise rejected"); 
}); 

Khi lời hứa $ scope.auctionsDiscoveryPromise đã được giải quyết tôi đang phát sóng một AUCTION_INIT sự kiện đang được lắng nghe trong chỉ thị của tôi. Tôi sử dụng thời gian chờ ngắn chỉ trong trường hợp một số dịch vụ hoặc chỉ thị chưa được khởi tạo.

0

Tôi đang sử dụng này nếu nó sẽ giúp bất cứ ai:

function getAll(items) { 

    var deferred = $q.defer(); 
    var dataRef = new Firebase(baseUrl + items); 
    var returnData = angularFireCollection(dataRef, function(data){ 
      deferred.resolve(data.val()); 
    }); 
    return deferred.promise; 

} 
Các vấn đề liên quan