2013-02-18 15 views
30

Buduję aplikację internetową przy użyciu AngularJS. Aplikacja musi odpytać adres URL, który zwraca dane JSON i udostępnia te dane dowolnej części aplikacji. Z tego co przeczytałem do tej pory, najlepiej jest stworzyć usługę, która obsługuje polling i zachowuje własny wewnętrzny bufor danych JSON, a następnie wstrzykuje usługę w dowolną część aplikacji, która chce skorzystać z tych danych. To, na czym jestem zagubiony, to jak właściwie to zrobić. Najbliższym znalezionym przykładem jest this question, ale wydaje się, że tworzy on usługę, która jest ręcznie wywoływana przez określony kontroler (który sam jest związany z daną trasą), natomiast chcę, aby coś, co nieustannie działa w tle aplikacji na zawsze niezależnie od tego, która część aplikacji jest aktywna. Czy to jest wykonalne, czy też podejmuję całkowicie błędne podejście?Usługa globalnego sondowania usługi AngularJS

Odpowiedz

41

Oto moje rozwiązanie:

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 
    }; 
}); 

(rozmowy po prostu pokazać, że pobieranie jest już zrobione)

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

EDIT: Jak Josh David Miller zasugerował w komentarzach, zależność ta należy dodać usługę w bloku app.run, aby zapewnić odpowiadanie od początku:

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

Przesunięto również harmonogram kolejnych ankiet po zakończeniu poprzedniego połączenia. Nie byłoby więc "układania" połączeń w przypadku, gdyby sondowanie trwało długo.

Zaktualizowany plunker.

+2

+1 Ale chce coś zawsze działa, więc także wywołać go od 'app.run' blo ck, aby upewnić się, że działa od początku. Sprawdziłbym również funkcję 'poller', aby upewnić się, że poprzednie połączenie z' $ http' zostało zakończone, aby nie składać się w nieskończoność, ale wydaje się, że nie można tego zrobić za pomocą implementacji obietnicy AngularJS. –

+1

Thnx. Dodano oba elementy do odpowiedzi. A o stosie można uniknąć, po prostu przesuwając harmonogram następnego sondowania na "wtedy" poprzedniego połączenia. Czyż nie? –

+1

Awesome! :-) Sądzę, że byłem tak skoncentrowany na oryginalnej "q'-obietniczej metodzie' isFulfilled() ', że' $ q' nie implementuje, że przegapiłem całkowicie oczywiste. lol –

20

Oto angular poller service na Github, który można łatwo wprowadzić do kontrolera.

Aby zainstalować: bower install angular-poller.

Ponieważ chcesz uruchomić usługę odpytywania globalny, który działa w tle zawsze można zrobić:

// 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); 
}); 

Teraz to będzie działać w tle zawsze aż zadzwonisz myPoller.stop() lub poller.stopAll().

Jeśli chcesz korzystać z danych zwrotnych tego Poller w innych kontrolerów, można po prostu zrobić:

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

Wygląda jak świetna biblioteka. Czy jest tam jakaś przykładowa aplikacja? – ardochhigh

+0

@ardochhigh Zamierzam wkrótce dodać przykładową aplikację. Ale zanim to nastąpi, możesz sprawdzić stronę [readme] (https://github.com/emmaguo/angular-poller/blob/master/README.md). :-) –

+0

Dzięki @Emma Guo strona README jest dość szczegółowa. Jestem dość nowy w Angular i wciąż mam problemy z niektórymi koncepcjami. Twoja biblioteka wygląda idealnie na moje potrzeby. Być może postaram się zrobić plunarza na dowód koncepcji. Dam ci znać. – ardochhigh

0

I rozwidlone @ ValentynShybanov kodzie fabrycznym i dodał Częstotliwość połączeń (co sekundę, co 5 sekund, etc), także można zatrzymać i uruchomić poller jak chcesz:

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 
    }; 
}); 
Powiązane problemy