मैं एक कोणीय घटक में स्थिति को संभालने से संबंधित एक छोटा सा प्रयोग कर रहा हूं।

मान लीजिए कि मेरे पास गणना करने के लिए एक चर महंगा है जो कई अन्य पर निर्भर करता है। मैं एक फ़ंक्शन updateVar() लिख सकता हूं और इसे हर उस घटना पर कॉल कर सकता हूं जो मुझे पता है कि इसे प्रभावित कर सकता है, उदाहरण के लिए। सदस्यता के माध्यम से। लेकिन जब उपरोक्त फ़ंक्शन को 5 से अधिक विभिन्न स्थानों पर बुलाया जाता है तो यह बहुत शुष्क और न ही मजबूत महसूस करता है।

तो इसके बजाय, DoCheck कोणीय जीवनचक्र हुक को डिबग करने के बारे में कैसे?

docheckSubject: Subject<any> = new Subject();
debounced: boolean = false;

constructor(private cd: ChangeDetectorRef) {}

ngOnInit() {
  this.docheckSubject.debounceTime(50).subscribe(
    () => this.ngDoCheckDebounced()
  );
}

ngDoCheck() {
  if (!this.debounced) {
    this.docheckSubject.next();
  } else {
    this.debounced = false;
  }
}

ngDoCheckDebounced() {
  this.debounced = true;
  this.updateVar();
  this.cd.detectChanges();  // needed to reflect update in DOM
}

यहां एक प्लंकर उदाहरण दिया गया है।

यह दृष्टिकोण मेरे असली ऐप में ठीक काम करता प्रतीत होता है, जहां निश्चित रूप से अधिक ngDoCheck() हो रहा है, और प्रोट्रैक्टर परीक्षण या तो शिकायत नहीं करते हैं। लेकिन मैं एक गंदी नहीं-तो-चालाक हैक करने की भावना को हिला नहीं सकता।

प्रश्न: क्या यह मुझे काटेगा? वास्तव में, क्या मुझे इसकी बिल्कुल आवश्यकता है?

1
Arnaud P 3 अगस्त 2017, 19:28

3 जवाब

सबसे बढ़िया उत्तर

बिना किसी समस्या (AFAICT) के उत्पादन में कई महीनों के बाद, मैंने इसे हटा दिया क्योंकि यह अंततः एक e2e (प्रोट्रैक्टर) परीक्षण को तब तक ब्लॉक करने का कारण बना जब तक कि कोई व्यक्ति मैन्युअल रूप से पृष्ठ पर क्लिक नहीं करेगा। जाहिर है टिकाऊ नहीं।

मैं इस समस्या के कारण का ठीक से निदान नहीं कर सका, हो सकता है कि यह हमारे कोड के असंबंधित हिस्से में एक विचित्रता से उत्पन्न हुआ हो, लेकिन खेद से बेहतर सुरक्षित है।

1
Arnaud P 16 मई 2018, 17:09

ngDoCheck को अक्सर कहा जाता है:

https://angular.io/guide/lifecycle-hooks#docheck

This hook is called with enormous frequency—after every change detection cycle no matter where the change occurred.

इस हुक का उपयोग वेरिएबल के अलावा किसी अन्य चीज़ के लिए करना एक बुरा विचार है जिसे एंगुलर परिवर्तन का पता लगाने के लिए नहीं जानता है। (उदाहरण के लिए, एक इनपुट ऑब्जेक्ट अपने गुणों में से किसी एक का मान बदल रहा है)। डिबगिंग कुछ हद तक मदद करता है, लेकिन आप अभी भी उस तर्क को बहुत बार निष्पादित कर रहे हैं, और ऐसा तब भी करना जारी रखेंगे जब आपको इसकी आवश्यकता नहीं होगी (यानी जब debounced == false)।

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

1
chrispy 3 अगस्त 2017, 19:40

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

ये रहा एक सरल उदाहरण:

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <div>x={{x}}</div>
      <div>y={{y}}</div>
      <button (click)="increment()">Increment</button>
      <div>Calculated Value={{calculatedValue}}</div>
    </div>
  `,
})
export class App {
  name:string;
  x: number = 0;
  y: number = 10;

  get calculatedValue(): number {
    return this.x * this.y;
  }

  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }

  increment(): number {
    this.x++;
  }

}

और संबद्ध प्लंकर: https://plnkr.co/edit/QC7mkbsbjRRBjJOjWSHe?p=preview

0
DeborahK 3 अगस्त 2017, 20:31