| Среда, 26 февраля, 2020
Метки: Angular, RxJS Комментарии: 0
Часто, например, реализовывая обмен данными между компонентами приходится создавать сервисы c observable переменными. Допустим, для того, чтобы изменения данных из одного компонента мы мгновенно получали в другом компоненте.
Одним из неудобств является то, что подписанное изменение нужно сохранить в объект Subscription и потом не забыть отписаться от него. Иначе это может привести в неожиданному поведению и багам, которые потом не всегда понятно из-за чего происходят.
@Component({ selector: 'app-test', template: ` <div>{{data1}}</div> <div>{{data2}}</div> `, }) export class TestComponent implements OnInit, OnDestroy { subs: Subscriptions = {}; data1: string; data2: number; constructor(private testService: TestService) { } ngOnInit(): void { this.subs.data1 = this.testService.data1$.subscribe(data1 => { this.data1 = data1; }); this.subs.data2 = this.testService.data2$.subscribe(data2 => { this.data2 = data2; }); } ngOnDestroy(): void { SubscriptionsHelper.unsubscribe(this.subs); } }
Если такая ситуация очень часто встречается в проекте, как вариант, можно добавить в общие файлы проекта класс со статичным методом, который аккумулирует такие подписки, и потом разом от них отписывается, Это вполне удобно, чтобы не следить для чего уже добавлена отписка, а для чего еще нет.
import {Subscription} from 'rxjs'; export interface Subscriptions { [key: string]: Subscription; } export class SubscriptionsHelper { static unsubscribe(subscriptions: Subscriptions) { Object.keys(subscriptions).forEach(key => { if (subscriptions[key]) { subscriptions[key].unsubscribe(); delete subscriptions[key]; } }); } }
И тогда исхлодный код самого первого примера можно оформить так:
export class TestComponent implements OnInit, OnDestroy { subs: Subscriptions = {}; // здесь меньше data1: string; data2: number; constructor(private testService: TestService) { } ngOnInit(): void { this.subs.data1 = this.testService.data1$.subscribe(data1 => { this.data1 = data1; }); this.subs.data2 = this.testService.data2$.subscribe(data2 => { this.data2 = data2; }); } ngOnDestroy(): void { SubscriptionsHelper.unsubscribe(this.subs); // здесь меньше } }Вроде все нормально, если бы не маленький нюанс, при сохранении подписок все равно нужно следить, чтобы свойства объекта subs не совпали: this.subs.data1 и this.subs.data2. Иначе объект подписки перезатрется и потом его уже SubscriptionHelper не отпишет в ngOnDestroy. Но все равно, за исключением этото недостатка, количество переменных за которыми нужно приглядывать уменьшилось.
Но на самом деле, если совсем нет потребности в явной подписке на observable-переменную в компоненте, то можно обойтись и более компактным решением, для этого нам поможет специальный пайп(pipe) async, который мы можем применить прямо в шаблоне компонента.
Еще больше зачищаем код исходного компонента, оставляя лишь сами observable-переменные.
@Component({ selector: 'app-test', template: `{{data1$ | async}}{{data2$ | async}}`, }) export class TestComponent implements OnInit { data1$: Observable; data2$: Obsevable ; constructor(private testService: TestService) { } ngOnInit(): void { this.data1$ = this.testService.data1$; this.data2$ = this.testService.data2$; } }
Итого, первоначальный вариант нашего компонента сократился почти в два раза, но не это главное. Главное, что он стал более читабельным и рафинированным, в котором отображена самая главная суть.
На небольшом примере — мы получили небольшой профит, но на крупных проектах, вы сэкономите большие объемы сил и времени, выполняя требуемую функциональность приложений, не делая лишних движений и не запутывая самих же себя.
Copyright © CodeHint.ru 2013-2024 (v2.4.7 - работает на Angular Universal)Калькулятор инвест-портфеля