Observable Stream
RxJS-ის ფუნდამენტური კონცეფცია არის observable stream, ანუ დაკვირვებადი მონაცემის ნაკადი. განვიხილოთ observable-ების ელემენტარული მაგალითები. ამისთვის გამოვიყენებთ ანგულარის საწყის აპლიკაციას.
როგორ მოვუსმენდით დოკუმენტში მაუსის დაკლიკებას? ჯავასკრიპტში ვიცით ივენთ ლისენერის გამოყენება, მაგრამ rxjs-ს თავისი ალტერნატივა აქვს. ეს არის fromEvent ოპერატორი, რომელიც უნდა დავაიმპორტოთ “rxjs”-დან.
import { Component, OnInit } from "@angular/core";
import { CommonModule } from "@angular/common";
import { fromEvent } from "rxjs";
@Component({
selector: "app-root",
standalone: true,
imports: [CommonModule],
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
// create an observable of mouse clicks on document
myObservable$ = fromEvent(document, "click");
ngOnInit(): void {}
}
მონაცემთა ნაკადი ნებისმიერი ინფორმაცია შეიძლება იყოს, თუმცა ყველაზე
ხშირად ეს ივენთებია. fromEvent
ოპერატორი შექმნის ჩვენთვის სასურველი
ელემენტის რაიმე მოვლენათა სტრიმს, მათ შორის click
-ს.
ამ სტრიმს ჩვენ ვინახავთ myObservable$
თვისებაში.
კონვენციურად ანგულარსი სტრიმებს ბოლოში დოლარის ნიშანს ვუწერთ.
ჩვენ კი შევქმენით სტრიმი, თუმცა ის არაფერს გააკეთებს.
სტრიმების კარგი ანალოგიაა წყალგაყვანილობა. წყალი არის მონაცემების ნაკადი,
თუმცა ის ჩვენამდე ვერ მოაღწევს, თუ ჩვენ ონკანს არ მოვუშვით. ონკანს რომ
მოვუშვათ, ამისთვის საჭიროა subscribe
მეთოდი, ანუ ამ სტრიმის გამოწერა.
import { Component, OnInit } from "@angular/core";
import { CommonModule } from "@angular/common";
import { Subscription, fromEvent } from "rxjs";
@Component({
selector: "app-root",
standalone: true,
imports: [CommonModule],
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
// create an observable of mouse clicks on document
myObservable$ = fromEvent(document, "click");
ngOnInit(): void {
// When component is initialized, start reacting
this.myObservable$.subscribe((event) => {
console.log(event);
});
}
}
ასე ჩვენ სტრიმს მივაწოდეთ subscribe
-ში ფუნქცია, რომელიც უნდა განხორციელდეს
ნაკადში ყოველი ახალი მონაცემის გამოჩენის დროს. ანუ ჩვენ ასე განვსაზღვრავთ როგორ
ვირეაგიროთ კონკრეტულ მოვლენებზე. ეს კონკრეტული სტრიმი მოვლენის
შესახებ ინფორმაციას გვაწვდის. ის უბრალოდ კონსოლში დავლოგოთ.
აქამდე observable-ის მაგალითი ნანახი გექნებათ HttpClient-თან მუშაობის დროს:
this.http.get("https://example.com").subscribe((response) => {
console.log(response);
});
რომელიც იგივე პრინციპით მუშაობს.
სუბსქრაიბ ფუნქციაში კონკრეტული ტიპის ობიექტის მიწოდებაც შეიძლება,
სადაც უფრო კონკრეტულად შეგვიძლია ვუთხრათ რა მომენტში რაზე გვინდა
რეაგირება. მაგალითად next
არის ნაკადში მონაცემის წარმატებით გაცემის
დროს განხორციელებული ფუნქცია. error
არის ნაკადში რაიმე ერორის
აღმოცენების დროს საპასუხო ფუნქცია და complete
არის ფუნქცია, რომელიც
უნდა განხორციელდეს როცა observable
დასრულდება.
// instead of a function, we will pass an object with next, error, and complete methods
myObservable.subscribe({
// on successful emissions
next: (event) => console.log(event),
// on errors
error: (error) => console.log(error),
// called once on completion
complete: () => console.log("complete!"),
});
სტრიმზე subscribe
მეთოდი აბრუნებს subscription-ს, რომელიც სურვილისამებრ შეგვიძლია
შევინახოთ ცვლადში. შესაძლებელია ერთზე მეტი subscription-ის შექმნა:
import { Component, OnInit } from "@angular/core";
import { CommonModule } from "@angular/common";
import { Subscription, fromEvent } from "rxjs";
@Component({
selector: "app-root",
standalone: true,
imports: [CommonModule],
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
// create an observable of mouse clicks on document
myObservable$ = fromEvent(document, "click");
mySubscription$!: Subscription;
mySubscriptionTwo$!: Subscription;
ngOnInit(): void {
this.mySubscription$ = this.myObservable$.subscribe((event) => {
console.log("subscription one", event);
});
this.mySubscriptionTwo$ = this.myObservable$.subscribe((event) => {
console.log("subscription two", event);
});
}
}
ჩვენ ორ ცალკეულ თვისებაში, რომლებიც subscription
ტიპის არიან, ვინახავთ
საბსქრიფშენებს.
აქ სტრიმებსა და მათ საბსქრიფშენებს შორის მიმართება რის ერთი ერთთან. ანუ ეს
იგივეა რაც ორი addEventListener
-ის გამოყენება და მასში ორი სხვადასხვა ფუნქციის
მიწოდება. თითოეულ საბსქრიბშენს ყავს თავისი ობზერვებლი. თუ გვსურს რომ ერთ
სტრიმზე დავასუბსქრაიბოთ სხვადასხვა ადგილას, მაშინ გვჭირდება Subject
-ების გამოყენება,
რომელზეც მოგვიანებით ვისაუბრებთ.
subscription-ის ინსტანცია შეიძლება მაშინ გამოგვადგეს, როცა
მაგალითად მოლენებისთვის მოსმენა აღარ გვიჭირდება. ამისთვის შეგვიძლია მასზე unsubscribe
მეთოდს დავუძახოთ. ეს ხშირად კომპონენტის განადგურების დროს არის საჭირო, რათა
მეხსიერება და სისტემის რესურსები დავზოგოთ. სტრიმების უყურადღებოდ დატოვება
აპლიკაციაში მეხსიერების პრობლემებს ქმნის.
import { Component, OnDestroy, OnInit } from "@angular/core";
import { CommonModule } from "@angular/common";
import { Subscription, fromEvent } from "rxjs";
@Component({
selector: "app-root",
standalone: true,
imports: [CommonModule],
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit, OnDestroy {
// create an observable of mouse clicks on document
myObservable$ = fromEvent(document, "click");
mySubscription$!: Subscription;
mySubscriptionTwo$!: Subscription;
ngOnInit(): void {
this.mySubscription$ = this.myObservable$.subscribe((event) => {
console.log("subscription one", event);
});
this.mySubscriptionTwo$ = this.myObservable$.subscribe((event) => {
console.log("subscription two", event);
});
}
ngOnDestroy(): void {
this.mySubscription$.unsubscribe();
this.mySubscriptionTwo$.unsubscribe();
}
}
ასე რომ არ მოვიქცეთ, სტრიმებზე მაშინაც გვექნება აქტიური სუბსქრაიბი, როცა სხვა კომპონენტზე ვიმყოფებით და ისინი რეალურად არ გვჭირდება.
RxJS-ის პლიუსი ის არის, რომ შეგვიძლია სტრიმების მრავალფეროვნად მანიპულაცია, მათი გაცემული მნიშვნელობების გარდაქმნა და სხვადასხვა სტრიმების გარკვეული გზებით კომბინაცია. ამისთვის ჩვენ ოპერატორებს ვიყენებთ.