angular - "एसिंक" पाइप स्ट्रीम अपडेट प्रदान नहीं कर रहा है




rxjs rxjs5 (2)

एक async पाइप का उपयोग करने वाले कोणीय 2 घटक में एक स्ट्रीम के माध्यम से विंडो आकार पर विंडो आकार को रेंडर करने की कोशिश कर रहा है:

<h2>Size: {{size$ | async | json}}</h2>

const windowSize$ = new BehaviorSubject(getWindowSize());
Observable.fromEvent(window, 'resize')
  .map(getWindowSize)
  .subscribe(windowSize$);

function getWindowSize() {
  return {
    height: window.innerHeight,
    width: window.innerWidth
  };
}

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>Size: {{size$ | async | json}}</h2>
    </div>
  `,
  directives: []
})
export class App {
  size$ = windowSize$.do(o => console.log('size:', o));
  constructor() {  }
}

लेकिन घटक केवल प्रारंभिक अवस्था प्रदान करता है और स्ट्रीम अपडेट को अनदेखा करता है। यदि आप कंसोल को खोलते हैं, तो विंडो रिसाइज पर, आप उसी स्ट्रीम से अपडेट देखेंगे।

समझ में नहीं आ रहा कि मुझे क्या याद आ रहा है।

यहाँ एक plunker है


चूंकि मेरा लक्ष्य अलग-अलग मॉड्यूल में खिड़की आकार की धाराओं को सार करने में सक्षम था, जाहिरा तौर पर सिर्फ एक कक्षा में धाराओं को लपेटकर सौदा सील कर दिया गया था:

"यह भविष्य है" संस्करण:

import {Observable, BehaviorSubject} from 'rxjs';  

export class WindowSize {
  width$: Observable<number>;
  height$: Observable<number>;

  constructor() {
    let windowSize$ = createWindowSize$();
    this.width$ = (windowSize$.pluck('width') as Observable<number>).distinctUntilChanged();
    this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();
  }
}

const createWindowSize$ = () =>
  Observable.fromEvent(window, 'resize')
    .map(getWindowSize)
    .startWith(getWindowSize())
    .publishReplay(1)
    .refCount();

const getWindowSize = () => {
  return {
    height: window.innerHeight,
    width: window.innerWidth
  }
};

"दादी" संस्करण:

import {Observable, BehaviorSubject} from 'rxjs';

export class WindowSize {
    width$: Observable<number>;
    height$: Observable<number>;

    constructor() {
        let windowSize$ = new BehaviorSubject(getWindowSize());
        this.width$ = (windowSize$.pluck('width') as Observable<number>).distinctUntilChanged();
        this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();

        Observable.fromEvent(window, 'resize')
            .map(getWindowSize)
            .subscribe(windowSize$);
    }
}

function getWindowSize() {
    return {
        height: window.innerHeight,
        width: window.innerWidth
    };
}

यद्यपि मैं इस मॉड्यूल में क्लास / सर्विस नहीं चाहता था, सिर्फ स्पष्ट / प्लेटफ़ॉर्म-स्वतंत्र निर्माण, यह एकमात्र साफ तरीका था जो ज़ोन अपडेट ट्रिगर करने की आवश्यकता के बिना कोणीय के लिए काम करता था।


इवेंट हैंडलर कोनालर जोन के बाहर चल रहा है, इसलिए इवेंट का उपयोग करते समय कोणीय परिवर्तन का पता चला नहीं है। अपने घटक के अंदर ईवेंट हैंडलर को रखो और फिर इसे अन्य सभी अतुल्यकालिक घटनाओं के साथ बंदर-पैच मिलेगा, इसलिए प्रत्येक घटना के बाद कोणीय परिवर्तन का पता चला जाएगा (और दृश्य अपडेट करें):

ngOnInit() {
    Observable.fromEvent(window, 'resize')
     .map(getWindowSize)
     .subscribe(windowSize$);
}

Plunker

एक अन्य विकल्प, टिप्पणियों में चर्चा की जाती है, जब एक दृश्य मॉडल को अपडेट किया जाता है तो मैन्युअल रूप से परिवर्तन का पता लगाने के लिए होता है:

import {Component, ChangeDetectorRef} from 'angular2/core'
...
export class App {
  size$ = windowSize$.do(o => {
     console.log('size:', o);
     // since the resize event was not registered while inside the Angular zone,
     // we need to manually run change detection so that the view will update
     this._cdr.detectChanges();
  });

  constructor(private _cdr: ChangeDetectorRef) {}
}

Plunker

नोट करें कि आप इसके बजाय एक बार ApplicationRef.tick() चलाने की कोशिश कर सकते हैं, अपने मूल घटक में कहते हैं, जो कि सभी घटकों पर परिवर्तन का पता ChangeDetectorRef.detectChanges() प्रत्येक घटक में ChangeDetectorRef.detectChanges() चलाने के बजाय। (और आपको एक setTimeout() विधि के अंदर tick() को लपेटने की आवश्यकता हो सकती है, यह सुनिश्चित करने के लिए कि सभी घटक दृश्य मॉडल अपडेट किए गए थे ... मुझे यकीन नहीं है जब सभी do() कॉलबैक विधियों को निष्पादित किया जाएगा - यानी, यदि वे सभी जावास्क्रिप्ट वीएम के एक मोड़ में भाग लेते हैं, या यदि कई मोड़ शामिल हैं।)





angular2-changedetection