简体   繁体   中英

Angular 6: subscribe component to a service event

I need to change message txt in a component according to a server response status. The problem is I don't know how to listen to that event in my component ts file and call a function declared in it. Maybe there is some better approach to show such notifications

handle error ts:

  catchErrors(resp:any) { if (resp.status == 200) { this.message = 'Запрос выполнен успешною Код: ' + resp.status; } else if (resp.status == 400) { this.message = 'Неверный запрос. Код ошибки: ' + status; } else if (resp.status == 404) { this.message = 'Сущность не найдена в системе. Код ошибки: ' + status; } else if (resp.status == 500) { this.message = 'Ошибка сервера. Код ошибки: ' + status; } return this.messageService.showMessage(this.message); } 

message service ts :

  showMessage(message) { return this.message = message; } 

And I need to run this function every time I get a response from a server. It is in messages.component.ts:

  showNotification() { this.message = this.messageService.message; } 

You can use subjects to get this job done :

In your message.service.ts declare a Subject :

messageSubject : Subject<string> = new Subject<string>();

Inside the showMessage() :

showMessage(message) {
    this.messageSubject.next(message);
 }

And in your component , inside the ngOnInit() , subscribe to the messageSubject like this :

this.messageService.messageSubject.subscribe((message : string) => {

//your message will be available here as ``message`` and you can implement your notification logic using this message 
}) 

Well, you can create a private BehaviorSubject<string> in your MessageService , and expose it as a public Observable by using asObservable .

You can also create a setMessage method on this service so that it could push the new message down the stream which the private BehaviorSubject<string> created.

This can then be used by the handleHandler .

And then you can simply subscribe to the public Observable that was exposed by your MessageService .

This would look something like this in code:

MessageService:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable()
export class MessageService {

  private message: BehaviorSubject<string> = new BehaviorSubject<string>(null);
  public message$: Observable<string> = this.message.asObservable();

  constructor(private http: HttpClient) { }

  getData() {
    this.http.get('https://jsonplaceholder.typicode.comm/users')
      .subscribe(
        res => console.log(res),
        err => this.errorHandler(err)
      );
  }

  setMessage(newMessage) {
    this.message.next(newMessage);
  }

  private errorHandler(error) {
    this.message.next('Got an error')
  }
}

Component:

import { Component } from '@angular/core';
import { MessageService } from './message.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  message;

  constructor(private messageService: MessageService) {}

  ngOnInit() {
    this.messageService.message$.subscribe(message => this.message = message);
    this.messageService.getData();
  }
}

Template:

<p>Message from the Message Service: {{ message }}</p>

There's just one catch here:

You can't create another service for error handling as your error handler service would rely on your message service and vice versa. This would create what is called a Circular Dependency and thus throw an error.


Here's a Sample StackBlitz for your ref.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM