2013-02-18 31 views
30

Tôi đang xây dựng một ứng dụng web bằng AngularJS. Ứng dụng cần thăm dò ý kiến ​​một URL trả về dữ liệu JSON và làm cho dữ liệu đó có sẵn cho bất kỳ phần nào của ứng dụng. Từ những gì tôi đã đọc cho đến nay, đặt cược tốt nhất của tôi là tạo một dịch vụ xử lý bỏ phiếu và lưu bộ nhớ cache nội bộ của dữ liệu JSON và sau đó tiêm dịch vụ vào bất kỳ phần nào của ứng dụng muốn tham khảo dữ liệu đó. Những gì tôi bị mất là làm thế nào để thực sự đi về việc đó. Ví dụ gần nhất mà tôi tìm thấy là this question, nhưng có vẻ như đang tạo một dịch vụ được gọi bằng bộ điều khiển cụ thể theo cách thủ công (chính nó được gắn với một tuyến nhất định), trong khi tôi muốn một thứ liên tục chạy trong nền ứng dụng mãi mãi bất kể phần nào của ứng dụng đang hoạt động. Điều này có thể thực hiện được không, hay tôi đang sử dụng cách tiếp cận hoàn toàn sai?AngularJS dịch vụ bỏ phiếu http toàn cầu

Trả lời

41

đây giải pháp của tôi:

app.factory('Poller', function($http, $timeout) { 
    var data = { response: {}, calls: 0 }; 
    var poller = function() { 
    $http.get('data.json').then(function(r) { 
     data.response = r.data; 
     data.calls++; 
     $timeout(poller, 1000); 
    });  
    }; 
    poller(); 

    return { 
    data: data 
    }; 
}); 

(cuộc gọi chỉ để hiển thị điểm bỏ phiếu được được thực hiện)

http://plnkr.co/edit/iMmhXTYweN4IrRrrpvMq?p=preview

EDIT: Như Josh David Miller gợi ý trong các ý kiến, sự phụ thuộc vào này nên thêm dịch vụ vào khối app.run để đảm bảo việc bỏ phiếu được thực hiện ngay từ đầu:

app.run(function(Poller) {}); 

Và cũng có thể di chuyển lịch biểu của cuộc thăm dò tiếp theo sau khi cuộc gọi trước kết thúc. Vì vậy, sẽ không có "xếp chồng" các cuộc gọi trong trường hợp nếu bỏ phiếu bị treo trong một thời gian dài.

Đã cập nhật plunker.

+2

+1 Nhưng anh muốn một cái gì đó luôn luôn chạy, vì vậy cũng kích hoạt nó từ một 'app.run' Blo ck để đảm bảo nó chạy từ đầu. Tôi cũng kiểm tra chức năng 'poller' để đảm bảo cuộc gọi trước đó thành' $ http' đã hoàn thành để chúng không chỉ xếp chồng lên nhau, nhưng có vẻ như không có cách nào để thực hiện điều đó với triển khai lời hứa AngularJS. –

+1

Thnx. Đã thêm cả hai mục vào câu trả lời. Và về việc ngăn xếp có thể tránh được bằng cách đơn giản di chuyển lịch biểu của cuộc thăm dò tiếp theo vào "sau đó" của cuộc gọi trước đó. Phải không? –

+1

Tuyệt vời! :-) Tôi đoán tôi đã quá tập trung vào phương thức hứa hẹn 'q' ban đầu của' isFulfilled() 'mà' $ q' không thực hiện mà tôi đã bỏ lỡ hoàn toàn hiển nhiên. lol –

20

Đây là một angular poller service trên Github có thể dễ dàng được đưa vào bộ điều khiển của bạn.

Để cài đặt: bower install angular-poller.

Vì bạn muốn bắt đầu một dịch vụ thăm dò toàn cầu chạy ở chế độ nền mãi mãi, bạn có thể làm:

// Inject angular poller service. 
var myModule = angular.module('myApp', ['poller']); 

// The home/init controller when you start the app. 
myModule.controller('myController', function($scope, $resource, poller) { 

    // Define your resource object. 
    var myResource = $resource(url[, paramDefaults]); 

    // Create and start poller. 
    var myPoller = poller.get(myResource); 

    // Update view. Most likely you only need to define notifyCallback. 
    myPoller.promise.then(successCallback, errorCallback, notifyCallback); 
}); 

Bây giờ nó sẽ chạy ở chế độ nền mãi mãi cho đến khi bạn gọi myPoller.stop() hoặc poller.stopAll().

Nếu bạn muốn sử dụng các dữ liệu callback của poller này trong bộ điều khiển khác, bạn chỉ có thể làm:

myModule.controller('anotherController', function($scope, $resource, poller) { 

    /* 
    * You can also move this to a $resource factory and inject it 
    * into the controller so you do not have to define it twice. 
    */ 
    var sameResource = $resource(url[, paramDefaults]); 

    /* 
    * This will not create a new poller for the same resource 
    * since it already exists, but will simply restarts it. 
    */ 
    var samePoller = poller.get(sameResource); 

    samePoller.promise.then(successCallback, errorCallback, notifyCallback); 
}); 
+0

Dường như một thư viện tuyệt vời. Có ứng dụng mẫu nào không? – ardochhigh

+0

@ardochhigh Tôi dự định sớm thêm ứng dụng mẫu. Nhưng trước khi điều đó xảy ra, bạn có thể kiểm tra trang [readme] (https://github.com/emmaguo/angular-poller/blob/master/README.md). :-) –

+0

Cảm ơn @Emma Guo trang README khá chi tiết. Tôi khá mới với Angular và vẫn đấu tranh với một số khái niệm. Thư viện của bạn trông hoàn hảo cho các yêu cầu của tôi. Có lẽ tôi sẽ cố gắng để làm cho một plunker cho một bằng chứng về khái niệm. Tôi sẽ cho bạn biết. – ardochhigh

0

tôi chia hai @ Code Factory ValentynShybanov và thêm khoảng cuộc gọi (mỗi giây, mỗi 5 giây, vv), bạn cũng có thể dừng lại và bắt đầu poller như bạn muốn:

http://plnkr.co/edit/EfsttAc4BtWSUiAU2lWf?p=preview

app.factory('Poller', function($http, $timeout) { 
    var pollerData = { 
    response: {}, 
    calls: 0, 
    stop: false 
    }; 

    var isChannelLive = function() { 
    $http.get('data.json').then(function(r) { 
     if (pollerData.calls > 30 && pollerData.stop === false) { // call every minute after the first ~30 secs 
     var d = new Date(); 
     console.log('> 30: ' + d.toLocaleString() + ' - count: ' + pollerData.calls); 
     pollerData.calls++; 
     $timeout(isChannelLive, 10000); 
     } else if (pollerData.calls > 15 && pollerData.calls <= 30 && pollerData.stop === false) { // after the first ~15 secs, then call every 5 secs 
     var d = new Date(); 
     console.log('> 15 & <= 30: ' + d.toLocaleString() + ' - count: ' + pollerData.calls); 
     pollerData.calls++; 
     $timeout(isChannelLive, 5000); 
     } else if (pollerData.calls <= 15 && pollerData.stop === false) { // call every 1 second during the first ~15 seconds 
     var d = new Date(); 
     console.log('<= 15: ' + d.toLocaleString() + ' - count: ' + pollerData.calls); 
     pollerData.calls++; 
     $timeout(isChannelLive, 1000); 
     } 

     pollerData.response = r.data; 
    }); 

    }; 
    var init = function() { 
    if (pollerData.calls === 0) { 
     pollerData.stop = false; 
     isChannelLive(); 
    } 
    }; 
    var stop = function() { 
    pollerData.calls = 0; 
    pollerData.stop = true; 
    }; 

    return { 
    pollerData: pollerData, // this should be private 
    init: init, 
    stop: stop 
    }; 
}); 
Các vấn đề liên quan