एंगुलरजेएस के साथ सर्वर मतदान


86

मैं 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 प्रतिक्रिया के लिए इंतजार किए बिना 1 अनुरोध का अनुरोध करता है और यूआई को स्पष्ट करता है। मुझे लगता है कि मुझे कॉलबैक फ़ंक्शन का उपयोग करने की आवश्यकता है। मैंने कोशिश की:

var x = Data.get({}, function () { });

लेकिन एक त्रुटि मिली: "त्रुटि: डेस्ट.पश एक फ़ंक्शन नहीं है" यह $ संसाधन के लिए डॉक्स पर आधारित था लेकिन मैं वास्तव में वहां के उदाहरणों को नहीं समझ पाया।

मैं दूसरे दृष्टिकोण को कैसे काम करूं?

जवाबों:


115

आपको tickकॉलबैक में फ़ंक्शन को कॉल करना चाहिए query

function dataCtrl($scope, $timeout, Data) {
    $scope.data = [];

    (function tick() {
        $scope.data = Data.query(function(){
            $timeout(tick, 1000);
        });
    })();
};

3
उत्कृष्ट धन्यवाद। मुझे नहीं पता था कि आप कॉलबैक को वहां रख सकते हैं। इसने स्पैमिंग समस्या को हल कर दिया। मैंने कॉलबैक के अंदर डेटा असाइनमेंट को भी स्थानांतरित किया जिसने यूआई क्लीयरिंग समस्या को हल किया।
डेव

1
मदद करने में सक्षम होने के लिए खुशी है! यदि यह समस्या हल हो जाती है, तो आप इस उत्तर को स्वीकार कर सकते हैं ताकि अन्य बाद में भी इससे लाभान्वित हो सकें।
अभा

1
उपरोक्त कोड मानकर पेजए और कंट्रोलर के लिए है। पेजबी और कंट्रोलरबी पर नेविगेट करने पर मैं इस टाइमर को कैसे रोकूं?
वरुण वर्मा

6
$ टाइमआउट रोकने की प्रक्रिया यहाँ docs.angularjs.org/api/ng.$timeout बताई गई है । मूल रूप से, $ टाइमआउट फ़ंक्शन एक वादा देता है जिसे आपको एक चर को निर्दिष्ट करने की आवश्यकता होती है। तब के लिए सुनो जब वह नियंत्रक नष्ट हो जाता है: $ गुंजाइश। $ पर ('नष्ट', fn ()) ;; कॉलबैक फ़ंक्शन में $ टाइमआउट की रद्द करने की विधि को कॉल करें और आपके द्वारा सहेजे गए वादे में पास करें: $ timeout.cancel (टाइमआउट वीयर); $ अंतराल डॉक्स वास्तव में एक बेहतर उदाहरण (है docs.angularjs.org/api/ng.$interval )
जस्टिन लुकास

1
@JustinLucas, बस मामले में यह $ गुंजाइश होना चाहिए। $ ('$ नष्ट', fn ());
टमाटर

33

कोणीय के अधिक हाल के संस्करणों ने $ अंतराल पेश किया है जो सर्वर मतदान के लिए $ समय से भी बेहतर काम करता है ।

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

17
-1, मुझे नहीं लगता कि $ अंतराल उपयुक्त है, क्योंकि आप अगला अनुरोध भेजने से पहले सर्वर की प्रतिक्रिया का इंतजार नहीं कर सकते। जब सर्वर में उच्च विलंबता होती है, तो इससे कई अनुरोध हो सकते हैं।
तूरुर

4
@ त्रेउर: जबकि यह इन दिनों पारंपरिक ज्ञान लगता है, मुझे यकीन नहीं है कि मैं सहमत हूं। ज्यादातर मामलों में मैं एक अधिक लचीला समाधान होगा। उस मामले पर विचार करें जहां कोई उपयोगकर्ता अस्थायी रूप से या आपके मामले के चरम पर जाता है जहां सर्वर एकल अनुरोध का जवाब नहीं देता है। यूआई $ टाइमआउट के उपयोगकर्ताओं के लिए अपडेट करना बंद कर देगा क्योंकि नया टाइमआउट सेट नहीं किया जाएगा। $ अंतराल के उपयोगकर्ताओं के लिए, यूआई पिकअप करेगा जहां कनेक्टिविटी के बहाल होते ही इसे छोड़ दिया गया। स्पष्ट रूप से समझदार देरी को चुनना महत्वपूर्ण है।
बॉब

2
मुझे लगता है कि यह अधिक सुविधाजनक है, लेकिन लचीला नहीं है। (रात में मेरे बेडरूम में एक शौचालय भी बहुत सुविधाजनक है, लेकिन अंततः यह खराब महक शुरू कर देगा;)) $ अंतराल का उपयोग करके वास्तविक डेटा प्राप्त करते समय आप सर्वर परिणाम की उपेक्षा करते हैं। यह आपके उपयोगकर्ता को सूचित करने, डेटा अखंडता की सुविधा या संक्षेप में: आपके एप्लिकेशन स्थिति को सामान्य रूप से प्रबंधित करने के लिए एक विधि का अभाव है। हालाँकि, आप इसके लिए सामान्य $ http इंटरसेप्टर्स का उपयोग कर सकते हैं और ऐसा होने पर $ अंतराल को रद्द कर सकते हैं।
तेरुर

2
यदि $ q वादों का उपयोग कर रहे हैं, तो आप बस यह सुनिश्चित करने के लिए कि कॉल विफल हो सकती है, अनुरोध अनुरोध विफल रहता है या नहीं, आखिरकार कॉलबैक का उपयोग कर सकते हैं।
टायसन नीरो

8
एक बेहतर विकल्प न केवल सफलता की घटना को संभालना होगा, बल्कि त्रुटि घटना भी होगी। इस तरह से यदि आप विफल होने पर दोबारा अनुरोध का प्रयास कर सकते हैं। आप इसे एक अलग अंतराल पर भी कर सकते हैं ...
मूंगफली

5

यहाँ पुनरावर्ती मतदान का उपयोग कर मेरा संस्करण है। इसका मतलब है कि यह अगली टाइमआउट शुरू करने से पहले सर्वर की प्रतिक्रिया का इंतजार करेगा। इसके अलावा, जब कोई त्रुटि होती है तो वह मतदान जारी रखेगा लेकिन एक अधिक आराम से मनोर में और त्रुटि की अवधि के अनुसार।

डेमो यहाँ है

यहाँ इसके बारे में और लिखा गया है

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

0

हम $ अंतराल सेवा का उपयोग करके आसानी से मतदान कर सकते हैं। यहाँ $ अंतराल के बारे में विस्तार से दस्तावेज दिया गया है
https://docs.angularjs.org/api/ng/service/$interval $ interval का उपयोग करने में
समस्या यह है कि यदि आप $ http सर्विस कॉलिंग या सर्वर इंटरैक्शन कर रहे हैं और यदि $ अंतराल से अधिक समय देरी हो रही है तब आपके एक अनुरोध पूरा होने से पहले, यह एक और अनुरोध शुरू करता है।
समाधान:
1. पोलिंग को सर्वर से सिंगल बिट या लाइटवेट जोंस जैसी सरल स्थिति प्राप्त होनी चाहिए ताकि आपके निर्धारित अंतराल समय से अधिक समय न लगे। आपको इस समस्या से बचने के लिए अंतराल के समय को उचित रूप से परिभाषित करना चाहिए।
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;
    }
}]);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.