рдХреЛрдгреАрдп рдореЗрдВ рдЕрд╡рд▓реЛрдХрди рд╕реЗрд╡рд╛рдПрдВ

рд╕рднреА рдХреЛ рдирдорд╕реНрдХрд╛рд░, рдореЗрд░рд╛ рдирд╛рдо рд╡реНрд▓рд╛рджрд┐рдореАрд░ рд╣реИред рдореИрдВ Tinkoff.ru рдореЗрдВ рдлреНрд░рдВрдЯ-рдПрдВрдб рдбреЗрд╡рд▓рдкрдореЗрдВрдЯ рдореЗрдВ рд▓рдЧрд╛ рд╣реВрдВред


рдХреЛрдгреАрдп рдореЗрдВ, рд╣рдо рд╕реЗрд╡рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕реА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЕрдВрджрд░ рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдпрд╛ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХреЛ рдПрдирдХреИрдкреНрд╕реБрд▓реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВред RxJS рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдзрд╛рдЧреЗ рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред


RxJS рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ рдХреЛрдгреАрдп рдЖрдкрдХреЛ рдПрдХ рдШреЛрд╖рдгрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓рдШреБ рдФрд░ рд╕реНрдкрд╖реНрдЯред рд▓реЗрдХрд┐рди рдХрднреА-рдХрднреА рд╣рдо рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдпрд╛ рдПрдкреАрдЖрдИ рдореЗрдВ рдЖрддреЗ рд╣реИрдВ рдЬреЛ рдХреЙрд▓рдмреИрдХ, рд╡рд╛рджреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рд╣рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рд╢реИрд▓реА рдХреЛ рддреНрдпрд╛рдЧрдиреЗ рдФрд░ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдХреНрдХрд╛ рдорд┐рд▓рддрд╛ рд╣реИред


рд▓реЗрдЦ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рд╕рдорд╛рди рдПрдкреАрдЖрдИ рдХреЗ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рджрд┐рдЦрд╛рдирд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ RxJS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдЖрд╕рд╛рдиреА рд╕реЗ рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓ рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдХреЛрдгреАрдп рдореЗрдВ рдкреНрд░рдпреЛрдЬреНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред рдЪрд▓реЛ рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред



рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдПрдкреАрдЖрдИ


рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрд╕рд╕реЗ рд╕рд╣рдордд рд╣реИ рддреЛ рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдПрдкреАрдЖрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрдкрдирд╛ рд╕реНрдерд╛рди рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЧреЛрдкрдиреАрдпрддрд╛ рдХрд╛рд░рдгреЛрдВ рд╕реЗ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕реНрдерд╛рди рдХреА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд╛рдВрдЧреА рдЬрд╛рдПрдЧреАред

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореВрд▓ рдЬрд┐рдпреЛрд▓реЛрдХреЗрд╢рди рдПрдкреАрдЖрдИ рдХреЗ рдореВрд▓ рдЙрдкрдпреЛрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИред


, Geolocation :


if('geolocation' in navigator) {
 /* geolocation is available */ 
} else {
 /* geolocation IS NOT available */ 
}

getCurrentPosition(), . watchPosition(), , . , .


...
success(position) {
 doSomething(position.coords.latitude, position.coords.longitude);
} 

error() {
 alert('Sorry, no position available.');
} 

watch() {
 this.watchID = navigator.geolocation.watchPosition(this.success, this.error);
}

stopWatch() {
  navigator.geolocation.clearWatch(this.watchID);
}
...

- , clearWatch() id . . . , RxJS Observable.


Geolocation, . . NAVIGATOR @ng-web-apis/common.


export const GEOLOCATION = new InjectionToken<Geolocation>(
   'An abstraction over window.navigator.geolocation object',
   {
       factory: () => inject(NAVIGATOR).geolocation,
   },
);

, Geolocation API:


export const GEOLOCATION_SUPPORT = new InjectionToken<boolean>(
   'Is Geolocation API supported?',
   {
       factory: () => !!inject(GEOLOCATION),
   },
);

PositionOptions:


import {InjectionToken} from '@angular/core';

export const POSITION_OPTIONS = new InjectionToken<PositionOptions>(
   'Token for an additional position options',
   {factory: () => ({})},
);

! Observable .


Observable, , , . , . Subscriber, , next(), complete() error(). , :


@Injectable({
   providedIn: 'root',
})
export class GeolocationService extends Observable<Position> {
   constructor(
       @Inject(GEOLOCATION) geolocationRef: Geolocation) {

       super(subscriber => {

           geolocationRef.watchPosition(
               position => subscriber.next(position),
               positionError => subscriber.error(positionError),
           );
       });
   }
}

:


@Injectable({
   providedIn: 'root',
})
export class GeolocationService extends Observable<Position> {
  constructor(
  @Inject(GEOLOCATION) geolocationRef: Geolocation,
  @Inject(GEOLOCATION_SUPPORT) geolocationSupported: boolean,
  @Inject(POSITION_OPTIONS) positionOptions: PositionOptions,
) {
  super(subscriber => {
    if (!geolocationSupported) {
      subscriber.error('Geolocation is not supported in your browser');
    }

    geolocationRef.watchPosition(
      position => subscriber.next(position),
      positionError => subscriber.error(positionError),
      positionOptions,
    );
   })
  }
}

! Observable, pipe(). RxJS- . , , RxJS- shareReplay().
share()? , Geolocation API getCurrentPosition() watchPosition() Timeout expired. shareReplay() , , . {bufferSize: 1, refCount: true}, . clearWatch()-, , RxJS- finalize():


@Injectable({
   providedIn: 'root',
})
export class GeolocationService extends Observable<Position> {
   constructor(
       @Inject(GEOLOCATION) geolocationRef: Geolocation,
       @Inject(GEOLOCATION_SUPPORT) geolocationSupported: boolean,
       @Inject(POSITION_OPTIONS)
       positionOptions: PositionOptions,
   ) {
       let watchPositionId = 0;

       super(subscriber => {
           if (!geolocationSupported) {
               subscriber.error('Geolocation is not supported in your browser');
           }

           watchPositionId = geolocationRef.watchPosition(
               position => subscriber.next(position),
               positionError => subscriber.error(positionError),
               positionOptions,
           );
       });

       return this.pipe(
           finalize(() => geolocationRef.clearWatch(watchPositionId)),
           shareReplay({bufferSize: 1, refCount: true}),
       );
   }
}

! , :


...
constructor(@Inject(GeolocationService) private readonly position$: Observable<Position>) {}
...
   position$.pipe(take(1)).subscribe(position => doSomethingWithPosition(position));
...

, async pipe. @angular/google-maps .


<app-map
       [position]="position$ | async"
></app-map>

RxJS .


Geolocation API. . npm.


ResizeObserver API , .


ResizeObserver API


API Resize Observer , .

Geolocation API, ResizeObserver API . Observable-. , . , , :


@Injectable()
export class ResizeObserverService extends Observable<
   ReadonlyArray<ResizeObserverEntry>
> {
   constructor(
       @Inject(ElementRef) {nativeElement}: ElementRef<Element>,
       @Inject(NgZone) ngZone: NgZone,
       @Inject(RESIZE_OBSERVER_SUPPORT) support: boolean,
       @Inject(RESIZE_OPTION_BOX) box: ResizeObserverOptions['box'],
   ) {
       let observer: ResizeObserver;

       super(subscriber => {
           if (!support) {
               subscriber.error('ResizeObserver is not supported in your browser');
           }

           observer = new ResizeObserver(entries => {
               ngZone.run(() => {
                   subscriber.next(entries);
               });
           });
           observer.observe(nativeElement, {box});
       });

       return this.pipe(
           finalize(() => observer.disconnect()),
           share(),
       );
   }
}

ResizeObserver. next() ngZone() .


Geolocation- , ElementRef. , observe(). . Dependency Injection , .


, . . Output(), :


@Directive({
   selector: '[waResizeObserver]',
   providers: [
       ResizeObserverService,
       {
           provide: RESIZE_OPTION_BOX,
           deps: [[new Attribute('waResizeBox')]],
           useFactory: boxFactory,
       },
   ],
})
export class ResizeObserverDirective {
   @Output()
   readonly waResizeObserver: Observable<ResizeObserverEntry[]>;

   constructor(
       @Inject(ResizeObserverService)
       entries$: Observable<ResizeObserverEntry[]>
   ) {
       this.waResizeObserver = entries$;
   }
}

, RESIZE_OPTION_BOX . ReziseObserver .


. , :


<div
       waResizeBox="content-box"
       (waResizeObserver)="onResize($event)"
   >
       Resizable box
</div>

...
   onResize(entry: ResizeObserverEntry[]) {
       // do something with entry
   }
...

open-source-, npm. ┬л┬╗.



RxJS Dependency Injection API, . . , тАФ , @ng-web-apis/midi. .


, .


, , Web APIs for Angular. тАФ API Angular-. , , , Payment Request API Intersection Observer, тАФ .


All Articles