Опрос сервера с помощью 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 но я действительно не понял примеры там.



как мне сделать второй подход?

496   4  

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

    Ничего не найдено.