For example in routing when we subscribe to route params:
this.route.params
.subscribe(
(params: Params) => { // data
this.id = +params['id'];
},
() => { // error
},
() => { // completion
}
);
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx'; //we also need to import rxjs/Rx. In general you'll be working with the observables provided by angular. You only need this import when you want to work with observable operators, that are part of the rxjs library
...
ngOnInit() {
// OBSERVABLE
const myNumbers = Observable.interval(1000); //RxJS, has some methods for creating observables. 'interval' will emit a new piece of data every second
// OBSERVER
myNumbers.subscribe(
(number: number) => {
console.log(number);
}
);
}
// 1) Create our custom observable
const myObservable = Observable.create((observer: Observer<string>) => { //'create' takes a function as argument, and this function should hold your asynchronous call.
// Receives an argument of type Observer. We are telling here to the observer when does it have to react.
// When you build an observable from scratch you need to build this bridge between the observable and the observer.
// We also configure the type of data it wille emit, a string
setTimeout(() => {
observer.next('first package'); //'next' emits a normal data package, pushes the next data package
}, 2000);
setTimeout(() => {
observer.next('second package');
}, 4000);
setTimeout(() => {
// observer.error('this does not work'); // emit an error
observer.complete(); // emit completion
}, 5000);
setTimeout(() => {
observer.next('third package'); // this never arrives as we've 'completed' the observable in the previous step
}, 6000);
});
// 2) Subscribe to the observable
myObservable.subscribe(
(data: string) => { console.log(data); },
(error: string) => { console.log(error); },
() => { console.log('completed'); }
);
Subscription
:customObsSubscription: Subscription;
...
ngOnInit() {
...
this.customObsSubscription = myObservable.subscribe(
...
);
}
Then unsubscribe from them onDestroy your component:
ngOnDestroy() {
this.customObsSubscription.unsubscribe();
}
** Observables built in in Angular clean themselves automatically**, but is a good practice to clean them on your own, and always when you're configuring your custom observables.
user.service.ts
import { Subject } from 'rxjs/Subject';
export class UserService {
userActivated = new Subject();
}
In our user component we'll use the service:
`<button (click)="onActivate()">Activate</button>`
onActivate() {
this.userService.userActivated.next(this.id); // A subject is the observable and the observer at the same time.
// Here we use the OBSERVER part, calling 'next' and passing a value, pushing a new data package
}
In our app component:
<a>User 1 {{ user1activated ? '(Active)' : '' }}</a>
<a>User 2 {{ user2activated ? '(Active)' : '' }}</a>
user1activated = false;
user2activated = false;
ngOnInit() {
this.userService.userActivated.subscribe( // userActivated is observer and observable at the same time,
// here we use the OBSERVABLE part and subscribe to it
(id: number) => {
if (id === 1) {
this.user1activated = true;
} else if (id === 2) {
this.user2activated = true;
}
}
);
}
EventEmitter
(indeed it is built on top of a Subject
). Next time you want to do cross-component communication, is best practice to use Subject
instead of EventEmitter
, and use next()
instead of emit()
to push a new value, and subscribe()
to consume it. You can also use the other functions (complete
, error
) and react to them. Also, don't forget to unsubscribe
when done.// make sure you import 'rxjs/Rx'
const myNumbers = Observable.interval(1000)
.map( //maps the data you get back, into a new observable with any transformation of your choice
(data: number) => {
return data * 2;
}
);