Angular2 में किसी सेवा की घटना की सदस्यता कैसे लें?


112

मुझे पता है कि EventEmitter के साथ एक घटना कैसे बढ़ाएं। अगर मेरे पास इस तरह का एक घटक है, तो मुझे भी बुलाया जा सकता है।

<component-with-event (myevent)="mymethod($event)" />

जब मेरे पास इस तरह का एक घटक होता है, तो सब कुछ बहुत अच्छा होता है। मैंने कुछ तर्क को एक सेवा में स्थानांतरित किया और मुझे सेवा के अंदर से एक घटना को बढ़ाने की आवश्यकता है। मैंने यह क्या किया:

export class MyService {
  myevent: EventEmitter = new EventEmitter();

  someMethodThatWillRaiseEvent() {
    this.myevent.next({data: 'fun'});
  }
}

मेरे पास एक घटक है जिसे इस घटना के आधार पर कुछ मूल्य को अपडेट करने की आवश्यकता है लेकिन मैं इसे काम नहीं कर सकता। मैंने जो कोशिश की वह यह थी:

//Annotations...
export class MyComponent {
  constructor(myService: MyService) {
    //myService is injected properly and i already use methods/shared data on this.
    myService.myevent.on(... // 'on' is not a method <-- not working
    myService.myevent.subscribe(.. // subscribe is not a method <-- not working
  }
}

जब मैं उस सेवा को बढ़ाता हूं, जो इस घटक को नहीं उठाती है, तो मैं MyComponent को इस घटना की सदस्यता कैसे दूं?

मैं 2.0.0-अल्फा.28 पर हूं

संपादित करें: वास्तव में काम करने के लिए मेरे "काम करने के उदाहरण" को संशोधित किया है, इसलिए ध्यान न देने वाले भाग पर रखा जा सकता है;)

उदाहरण कोड: http://plnkr.co/edit/m1x62WoCHpKtx0uLNsIv


1
यह डिजाइन का एक मुद्दा हो सकता है क्योंकि एक घटक की ओर से एक सेवा को घटनाओं का उत्सर्जन नहीं करना चाहिए, क्योंकि यह कसकर घटक को सेवा प्रदान करता है। उदाहरण के लिए यदि घटक के कई उदाहरण हैं, तो क्या उन सभी को उस स्थिति में घटनाओं का उत्सर्जन करना चाहिए?
कोणीय विश्वविद्यालय

@ झदेशदेव मैंने आपको पढ़ा। मैंने समाधान को फिर से डिज़ाइन किया ताकि सेवा को परिणाम का अनुकरण करने की आवश्यकता न हो। मुझे अभी भी लगता है कि कुछ डिज़ाइन घटनाओं को बढ़ाने में सक्षम होंगे - यह किस तरह की "सेवा" पर निर्भर करता है ...
हॉर्नशो-स्ज़ेबेक

एक तरीका तो यह हो सकता है कि घटक सेवा के बजाय ईवेंट एमिटर का निर्माण कर सकता है, और फिर इवेंट एमिटर में सेवा के तर्क के रूप में पास हो सकता है
कोणीय विश्वविद्यालय

जवाबों:


135

अद्यतन : मैंने इस समस्या को हल करने के लिए एक बेहतर / उचित तरीका ढूंढ लिया है, जो कि ईवेंटवेयर के बजाय एक व्यवहार-अवलोकन या एक अवलोकन योग्य का उपयोग कर रहा है। कृपया इस उत्तर को देखें: https://stackoverflow.com/a/35568924/215945

इसके अलावा, कोणीय डॉक्स में अब एक कुकबुक उदाहरण है जो एक विषय का उपयोग करता है


मूल / पुराना / गलत उत्तर: फिर से, किसी सेवा में EventEmitter का उपयोग न करें । यह एक विरोधी पैटर्न है।

Beta.1 का उपयोग करते हुए ... NavService में EventEmiter होता है। घटक नेविगेशन सेवा के माध्यम से घटनाओं का उत्सर्जन करता है, और घटक अवलोकनशीलकंपोनेंट घटनाओं की सदस्यता लेता है।

nav.service.ts

import {EventEmitter} from 'angular2/core';
export class NavService {
  navchange: EventEmitter<number> = new EventEmitter();
  constructor() {}
  emitNavChangeEvent(number) {
    this.navchange.emit(number);
  }
  getNavChangeEmitter() {
    return this.navchange;
  }
}

components.ts

import {Component} from 'angular2/core';
import {NavService} from '../services/NavService';

@Component({
  selector: 'obs-comp',
  template: `obs component, item: {{item}}`
})
export class ObservingComponent {
  item: number = 0;
  subscription: any;
  constructor(private navService:NavService) {}
  ngOnInit() {
    this.subscription = this.navService.getNavChangeEmitter()
      .subscribe(item => this.selectedNavItem(item));
  }
  selectedNavItem(item: number) {
    this.item = item;
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'my-nav',
  template:`
    <div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
    <div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
  `,
})
export class Navigation {
  item = 1;
  constructor(private navService:NavService) {}
  selectedNavItem(item: number) {
    console.log('selected nav item ' + item);
    this.navService.emitNavChangeEvent(item);
  }
}

Plunker


मैंने इसका अनुसरण किया है, लेकिन यह केवल कक्षा के लिए ही काम करता है। यह किसी अन्य वर्ग (दूसरी फ़ाइल से) के लिए काम नहीं कर रहा है। ऐसा लगता है कि समस्या सेवा वर्ग के उदाहरण में है। सेवा वर्ग को स्थिर बनाने के लिए क्या कोई रास्ता है?
असुबनोव्स्की

5
@asubanovsky, प्लंकर में मैं केवल बूटस्ट्रैप (यानी, रूट कंपोनेंट) स्तर पर NavService इंजेक्ट करता हूं, इसलिए पूरे ऐप के लिए सेवा का केवल एक उदाहरण होना चाहिए। क्या आप इसे कहीं और इंजेक्ट कर रहे हैं providers: [NavService]? यदि हां, तो आपको सेवा के कई उदाहरण मिलेंगे।
मार्क राजकॉक

आपका बहुत बहुत धन्यवाद। यह अब मेरी उम्मीद के रूप में काम कर रहा है। अब मैं बूटस्ट्रैप स्तर और घटक स्तर पर प्रदाताओं को इंजेक्ट करने के बीच के अंतर को समझता हूं।
असुबनोव्स्की

इस पोस्ट को गंभीरता से एक ऐसी स्थिति में बदल दिया गया था जहाँ अब मैं 'नहीं मिलता'। क्यों सेवा पर एक mehtod कॉल कर रहा है .getNavChangeEmitter () जो कि EventEmitter को सीधे नवचेंज की सदस्यता लेने से अलग करता है?
प्रति हॉर्नशोज-शियरबेक

@ PerHornshøj-Schierbeck, मैंने इस तथ्य को छिपाने के लिए विधि getNavChangeEmitter () का उपयोग किया कि इस सेवा के अंदर एक EventEmitter का उपयोग किया जा रहा था। विधि के उपयोगकर्ता यह मान सकते हैं कि लौटी हुई वस्तु में एक subscribe()विधि है। एक विधि का उपयोग करके, हम आसानी से EventEmitter को एक विषय या एक अवलोकन के लिए बदल सकते हैं, जो कि बहुत बेहतर है, क्योंकि हमने अब सीखा है कि EventEmitters का उपयोग केवल आउटपुट गुणों के लिए किया जाना चाहिए। उचित तरीका यह है कि आप किसी Subject, BehaviorSubject या Observable का उपयोग करें, और हम आम तौर पर सीधे इनकी सदस्यता लेते हैं, इसलिए हमें अब GetNavChangeEmitter () विधि की आवश्यकता नहीं है।
मार्क राजकोक

6

अल्फा 28 का उपयोग करते हुए, मैंने eventEmitter.toRx().subscribe(..)विधि के माध्यम से कार्यक्रम उत्सर्जकों की सदस्यता लेने के लिए प्रोग्रामेटिक रूप से पूरा किया । जैसा कि यह सहज नहीं है, यह शायद भविष्य के रिलीज में बदल सकता है।


1
शायद लोगों को इस पद पर ठोकर खाने के लिए एक सरल उदाहरण प्रदान करें? यह मुझे btw डाउनवोटिंग नहीं था;)
हॉर्नशो-शियरबेक

2
पता नहीं क्यों इसे डाउन वोट दिया गया था, यह निश्चित रूप से काम करता है। सीधे शब्दों में कहें, एक घटना emitter की सदस्यता के लिए "क्लिक", उपयोग click.toRx().subscribe(your_callback_function)
Runeboy

मुझे लगता है कि इसे अस्वीकार कर दिया गया हो सकता है क्योंकि इसमें काम करने की कमी है? मैं जानता हूँ कि इसके लायक एक वोट दें और शायद एक स्वीकार किए जाते हैं जवाब अगर यह वाक्य रचना बेहतर प्रदर्शित करने के लिए एक pluncker / jsfiddle बेला या यहाँ तक कि कोड के कुछ लाइनों के लिए या तो एक कड़ी था हो सकता है;)
प्रति Hornshøj-Schierbeck

मुझे उदाहरण मिल रहा है: ReferenceError: क्लिक को परिभाषित नहीं किया गया है @ Runeboy क्या आप कृपया अपने समाधान के लिए एक plnkr प्रदान कर सकते हैं?
बेंजामिन मैकफेरेन 23

आपको एक EventEmitter को परिभाषित करने की आवश्यकता है जिसे काम करने के लिए क्लिक करें
Mazen Elkashef
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.