Опрос сервера с помощью AngularJS
Я пытаюсь узнать AngularJS. Моя первая попытка получить новые данные каждую секунду работали:
'use strict';
function dataCtrl($scope, $http, $timeout) {
$scope.data = [];
(function tick() {
$http.get('api/changingData').success(function (data) {
$scope.data = data;
$timeout(tick, 1000);
});
})();
};
когда я имитирую медленный сервер, спящий поток в течение 5 секунд, он ждет ответа перед обновлением пользовательского интерфейса и установкой другого таймаута. Проблема в том, когда я переписал выше, чтобы использовать угловые модули и DI для создания модуля:
'use strict';
angular.module('datacat', ['dataServices']);
angular.module('dataServices', ['ngResource']).
factory('Data', function ($resource) {
return $resource('api/changingData', {}, {
query: { method: 'GET', params: {}, isArray: true }
});
});
function dataCtrl($scope, $timeout, Data) {
$scope.data = [];
(function tick() {
$scope.data = Data.query();
$timeout(tick, 1000);
})();
};
это работает только при быстром ответе сервера. Если есть какая-либо задержка, он выдает 1 запрос в секунду без ожидание ответа и, кажется, очистить пользовательский интерфейс. Я думаю, мне нужно использовать функцию обратного вызова. Я попробовал:
var x = Data.get({}, function () { });
, но получил сообщение об ошибке: "ошибка: пункт назначения.push-это не функция" это было основано на документах для $ resource но я действительно не понял примеры там.
как мне сделать второй подход?
4 ответов:
вы должны позвонить
tickфункция обратного вызоваquery.function dataCtrl($scope, $timeout, Data) { $scope.data = []; (function tick() { $scope.data = Data.query(function(){ $timeout(tick, 1000); }); })(); };
более поздние версии angular ввели $ interval, который работает даже лучше, чем $ timeout для опроса сервера.
var refreshData = function() { // Assign to scope within callback to avoid data flickering on screen Data.query({ someField: $scope.fieldValue }, function(dataElements){ $scope.data = dataElements; }); }; var promise = $interval(refreshData, 1000); // Cancel interval on page changes $scope.$on('$destroy', function(){ if (angular.isDefined(promise)) { $interval.cancel(promise); promise = undefined; } });
вот моя версия с использованием рекурсивного опроса. Это означает, что он будет ждать ответа сервера перед началом следующего таймаута. Кроме того, при возникновении ошибки он будет продолжать опрос, но в более спокойной усадьбе и в соответствии с продолжительностью ошибки.
var app = angular.module('plunker', ['ngAnimate']); app.controller('MainCtrl', function($scope, $http, $timeout) { var loadTime = 1000, //Load the data every second errorCount = 0, //Counter for the server errors loadPromise; //Pointer to the promise created by the Angular $timout service var getData = function() { $http.get('http://httpbin.org/delay/1?now=' + Date.now()) .then(function(res) { $scope.data = res.data.args; errorCount = 0; nextLoad(); }) .catch(function(res) { $scope.data = 'Server error'; nextLoad(++errorCount * 2 * loadTime); }); }; var cancelNextLoad = function() { $timeout.cancel(loadPromise); }; var nextLoad = function(mill) { mill = mill || loadTime; //Always make sure the last timeout is cleared before starting a new one cancelNextLoad(); $timeout(getData, mill); }; //Start polling the data from the server getData(); //Always clear the timeout when the view is destroyed, otherwise it will keep polling $scope.$on('$destroy', function() { cancelNextLoad(); }); $scope.data = 'Loading...'; });
мы можем сделать это опрос легко с помощью $interval service. вот подробный документ о $ interval
https://docs.angularjs.org/api/ng/service / $interval
использование $interval заключается в том, что если вы выполняете вызов службы $http или взаимодействие с сервером, и если задержка превышает время $interval, то до завершения одного запроса он запускает другой запрос.
устранение:
1. Опрос должен быть простым получением статуса сервер, как один бит или легкий json, поэтому не должен занимать больше времени, чем ваш определенный интервал времени. Вы также должны определить время интервала соответствующим образом, чтобы избежать этой проблемы.
2. Каким-то образом это все еще происходит по какой-либо причине, вы должны проверить глобальный флаг, что предыдущий запрос завершен или нет перед отправкой любых других запросов. Он пропустит этот интервал времени, но он не будет отправлять запрос преждевременно.
Также, если вы хотите установить пороговое значение, которое после некоторого значения так или иначе опрос должен быть установлен, то вы можете сделать это следующим образом.
Вот рабочий пример. объяснил подробно здесьangular.module('myApp.view2', ['ngRoute']) .controller('View2Ctrl', ['$scope', '$timeout', '$interval', '$http', function ($scope, $timeout, $interval, $http) { $scope.title = "Test Title"; $scope.data = []; var hasvaluereturnd = true; // Flag to check var thresholdvalue = 20; // interval threshold value function poll(interval, callback) { return $interval(function () { if (hasvaluereturnd) { //check flag before start new call callback(hasvaluereturnd); } thresholdvalue = thresholdvalue - 1; //Decrease threshold value if (thresholdvalue == 0) { $scope.stopPoll(); // Stop $interval if it reaches to threshold } }, interval) } var pollpromise = poll(1000, function () { hasvaluereturnd = false; //$timeout(function () { // You can test scenario where server takes more time then interval $http.get('http://httpbin.org/get?timeoutKey=timeoutValue').then( function (data) { hasvaluereturnd = true; // set Flag to true to start new call $scope.data = data; }, function (e) { hasvaluereturnd = true; // set Flag to true to start new call //You can set false also as per your requirement in case of error } ); //}, 2000); }); // stop interval. $scope.stopPoll = function () { $interval.cancel(pollpromise); thresholdvalue = 0; //reset all flags. hasvaluereturnd = true; } }]);
Comments