लो-डैश के साथ AngularJS फ़िल्टर कैश

तेज बाघ के रूप में AngularJS ^ ^

मैं एक डिप्लोमा लिख ​​रहा हूं जहां मैं समस्याओं में से एक को हल करता हूं - अनाम तेज वेब चैट का कार्यान्वयन। हर मायने में तेज - डाउनलोड, एप्लिकेशन ऑपरेशन, उपयोग (दूर प्राधिकरण)। विकल्प एक गुच्छा पर बंद हो गया: ग्राहक पक्ष पर Node.js फ्रेमवर्क सॉकेटस्ट्रीम और एंगुलरजेएस । इस प्रक्रिया में, मैं एक समस्या में चला गया - एक ही मॉडल पर फ़िल्टर द्वारा की गई बार-बार गणना। कट के तहत समस्या और समाधान का विवरण।



पाठक स्तर:
AngularJS: मध्यम (फ़िल्टर बनाना)
लो-डैश: "देखा-महसूस किया"

सीधे समाधान पर जाएं


समस्या विवरण में है


हमारे पास एक बड़ा सरणी है जिसके साथ हमारा एप्लिकेशन लगातार इसके तत्वों में हेरफेर करके काम करता है। सरणी के लिए एक सरणी फ़िल्टर लागू किया जाना चाहिए, उदाहरण के लिए, तिथि द्वारा छंटनी और एक विशिष्ट संपत्ति वाले तत्वों को उजागर करना। हम इस समस्या को एप्लिकेशन क्षेत्र में स्थानांतरित करेंगे - मेरी चैट का एक सरलीकृत संस्करण। एरे के तत्व चैट (कमरे / सर्कल) हैं जिनमें संदेश होते हैं। चैट में निम्नलिखित संरचना है:

{ id: 'rE4aA', title: ' ', online: 3, recent: 0, //    messages: [] //  } 

मैं ngRepeat {N} निर्देश (स्क्रीन आकार के आधार पर) का उपयोग करके पृष्ठ पर चैट की संख्या प्रदर्शित करना चाहता हूं। और मैं एक संदर्भ मेनू प्रदर्शित करना चाहता हूं जो किसी भी चैट के शीर्षक पर सही माउस बटन पर क्लिक करके प्रकट होता है और आपको चयनित चैट को दूसरे स्थान पर ले जाने की अनुमति देता है। यह कैसा दिखता है:

चैट शीर्षक पर राइट क्लिक करें
चैट शीर्षक पर राइट क्लिक करें

चैट का मुख्य आकर्षण, जिस स्थान पर हम आंदोलन को चिह्नित करते हैं
चैट का मुख्य आकर्षण, जिस स्थान पर हम आंदोलन को चिह्नित करते हैं

इस तरह की कार्यक्षमता ngRepeat निर्देश के साथ दो सूची बनाकर और एक फ़िल्टर लागू करके लागू की जा सकती है। चैट के लिए, फ़िल्टर नए संदेशों (हाल ही में संपत्ति) की संख्या और तत्वों (चैट) की संख्या को कम करके {N} करने में सक्षम होना चाहिए जो कि ब्राउज़र विंडो के आकार से गणना की जाती है। संदर्भ मेनू के लिए - वर्तमान तत्व को छोड़कर एक ही फ़िल्टर (जिस हेडर पर क्लिक किया गया था)।

फ़िल्टर कोड:
 angular.module('app') .filter('opened', ['$rootScope', function($s){ return function(o){ console.log('  «opened»'); var count = $s.count; //  ,  {N} return _(o) //    Lo-Dash .sortBy('recent') //      .reverse() //  (   ) .first(count) //   {N}  .value() //   } }]); 

प्रत्येक ngRepeat डायरेक्टिव को पास किए गए एरे तर्क में इस फिल्टर को लागू करने पर, ngRepeat देखते हैं कि कंसोल में "ओपन फ़िल्टर लागू" संदेश दो बार दिखाया गया है। इसका मतलब है कि फ़िल्टर द्वारा संसाधनों के आधे बर्बाद कर दिए गए थे। संदर्भ मेनू के रूप में इस तरह की सुविधा ने आवेदन की वर्तमान स्थिति को प्रस्तुत करने के समय को दोगुना कर दिया। और अगर मैं फ़िल्टर के साथ समान डेटा का उपयोग करके कार्यक्षमता जोड़ना जारी रखता हूं, तो स्थिति और भी खराब हो जाएगी।


समस्या हल करना


समाधान एक फ़ंक्शन बनाने के लिए है जो फ़िल्टर किए गए सरणी देता है। यह फ़ंक्शन मूल फ़िल्टर प्रदाता का उपयोग किए बिना मूल सरणी के बजाय उपयोग किया जाता है। लो-डैश प्रॉपर्टी में फ़ंक्शन रैप होता है , जो कैशिंग कार्यक्षमता को कार्यान्वित करता है। नीचे मैं बताऊंगा कि ज्ञापन कैसे काम करता है और एक उदाहरण कार्यान्वयन देता है।


लो-डैश प्रॉपर्टी याद आती है


तर्क:
  1. - (आवश्यक) - इस फ़ंक्शन का कैश्ड परिणाम ज्ञापन देता है
  2. - (वैकल्पिक) - फ़ंक्शन का परिणाम कैश की है (विशिष्टता के लिए जांच)

_.memoize (fn, [fn]) एक फ़ंक्शन लौटाता है, पहली बार इसे कहा जाता है, यह गणना करता है, परिणाम याद रखता है (एक कैश बनाता है) और इसे वापस करता है। इसके बाद कॉल एक कैश वापस करते हैं। यह सब एक कैश कुंजी के लिए सही है।

कैश कुंजी फ़ंक्शन के परिणाम से निर्धारित होती है, जिसे दूसरे तर्क के रूप में पास किया जाता है। डिफ़ॉल्ट रूप से (जब तक कि दूसरा तर्क निर्दिष्ट नहीं किया जाता है) मेमो पहले कैश तर्क के रूप में पहले तर्क का उपयोग करता है।


एक ज्वलंत उदाहरण पर


शॉर्ट लिस्टिंग के अंत में डेमो के लिए एक लिंक होगा, लेकिन मैं कोड में टिप्पणियों पर ध्यान देने का सुझाव देता हूं।

हम एक सरेस से जोड़ा हुआ "फॉर्म" ऑब्जेक्ट के साथ एक साधारण नियंत्रक बनाते हैं:
 function MyController($scope){ $scope.form = { input: {key:'', val:''}, //       array: [ {key:'pear', val:''}, //  {key:'melon', val:''}, {key:'ananas', val:''}, {key:'cherry', val:''} ], order: 'key', //      key (2  key/val) check: false, //      .   (2  — true/false) add: function(){ //          this.array.push(angular.copy(this.input)); this.filtered.cache = {} //    }, filtered: _.memoize( //   function(){ console.log('  : ' + this.order + '  ' + this.check); return _.sortBy(this.array, this.order) }, function(){ //  - //      return [this.order, this.check] } ) } } 

HTML का एक सा:
 <form name="myform" ng-app ng-controller="MyController"> <input type="text" required ng-model="form.input.key" placeholder="key"> <input type="text" required ng-model="form.input.val" placeholder="val"> <button ng-disabled="!myform.$valid" ng-click="form.add()"></button><br><br> <fieldset> <legend>   : <select ng-model="form.order" ng-options="p for p in ['key', 'val']"></select> </legend> <div ng-repeat="el in form.filtered()"> {{el.key}} — "{{el.val}}" </div><br> <label> <input type="checkbox" ng-model="form.check">   -   </label><hr> <pre>{{form.filtered()|json}}</pre> </fieldset> </form> 

आइए देखते हैं परिणाम jsFiddle परCtrl + Shift + J (Chrome ब्राउज़र के लिए प्रासंगिक) के साथ कंसोल खोलें। हम झंडे को स्विच करने और ध्वज को खींचने की कोशिश करते हैं। कंसोल में, हम फ़िल्टर फ़ंक्शन की अधिकतम 4 शुरुआत (प्रत्येक राज्यों के लिए) देखते हैं। सरणी में एक नया तत्व जोड़ना - कैश रीसेट करें और फिर से सुनिश्चित करें कि यह समाधान सही तरीके से काम करता है।

अद्भुत लो-डैश लाइब्रेरी और विशेष रूप से ज्ञापन संपत्ति के लिए धन्यवाद, मैं एंगुलरजेएस आवेदन की गति को बढ़ाने में सक्षम था। अगर मैंने एक देशी फ़िल्टर लागू किया, जिस क्षण से एप्लिकेशन लॉन्च किया गया था, फ़िल्टर ने 1 के खिलाफ 8 बार काम किया (मेमोइज़ के साथ समाधान)।

मैं समुदाय से रचनात्मक आलोचना और देशी फिल्टर के "पंपिंग" के तरीकों के बारे में सोचता हूं।

पुनश्च: मैं हैबर के निमंत्रण के लिए यूएफओ को धन्यवाद देता हूं।

Source: https://habr.com/ru/post/In200130/


All Articles