Angular 2. Пример подписки на ответ http запроса без непосредственной отправки.

Как-то обсуждали в одном из чатов, поэтому пусть будет небольшая заметка.

Вообще-то это вопрос не angular-а, а скорее reactivex паттернов.

Предположим есть компонент, в котором необходимо получить результаты запроса к серверу, например, к rest api методу.

Запрос можно делать и в самом компоненте.
Например так:


import {Http} from '@angular/http';

@Component({ ... })
export class SomeComponent {
	
	constructor(private http: Http){

	}

	calHttpMethod(){

		this.http.post( ... ).subscribe(
			(response) => {

				// handle response here
			}
		);
	}
}

Но, когда проект разрастается, удобней использовать для обмена с сервером прослойкой — сервисом.

Это все тот же простой класс. Дополниельно только добавится декоратор @Injectable, для указания того, что этот простой класс можно использовать для внедрения.

Получается задача разбивается на две части.

В компоненте внедряется сервис и выполняется подписка на ответы от сервера.

А в сервисе создается ответ и отправляется запрос к серверу.

Компонент:

someService — внедренный через di инстанс сервиса
apiResponseSubscription — поле для подписки на события сервиса. Можно обработку ответа разместить тут же, а можно сделать вызов метода компонента.

на этапе OnInit осуществляется собственно сама подписка. Не забываем на этапе OnDestroy отписаться

в какой-то момент (например, по действию пользователя) вызывается метод initServerCall, т.е. вызов метода serverCall сервиса.

Для компонента все — теперь код обработки ответа сработает только в случае генерации события сервисом.


// angular Component 

import {Component, OnInit, OnDestroy} from '@angular/core';
import {SomeService} from 'some.service';
import {Subscription} from 'rxjs';


@Component({ ... })
export class someComponent implements OnDestroy {
	
	private apiResponseSubscription: Subscription;

	constructor(private someService: SomeService){}

	
	ngOnInit(){

		this.apiResponseSubscription = this.someService.serverResponse.subscribe(
			(response) => {
				// response handle here
			}
		);
	}

	/**
	 * method that initate server call
	 */
	initServerCall(){
		this.someService.serverCall();
	}

	/**
	 * unsbscribe at end of lifecycle
	 */
	ngOnDestroy(){
		if(this.apiResponseSubscription){
			this.apiResponseSubscription.unsubscribe();
		}
	}

}

Сервис

serverResponse — геттер, возвращающий Observable (в этом примере — ReplaySubject).

Для данного примера может быть любой Observable или Promise, позволяющий подписаться на себя через Subscription и метод subscribe.

http — инжектированный через di класс Http.

serverCall — метод, в котором непосредственно отправляется запрос на сервер.


import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import {ReplaySubject} from 'rxjs';


@Injectable()
export class SomeService {
	
	private someServerResponse: ReplaySubject = new ReplaySubject(1);

	constructor(private http: Http) {}

	get serverResponse(): ReplaySubject {
		return this.someServerResponse;
	}
	
	serverCall(params: any = {}): void {
		this.http.post(  ).subscribe(
			(response) => {
				// some actions may be here
				this.someServerResponse.next(response); // instead response may be other values
			});
	}

}

Итак. Сервис может быть универсальным. Поэтому вместо прямого доступа к полю ответа лучше получить его через get метод.

Сервис инжектится в компонент и, в данном случае, на этапе инициализации подписывается на ответ от сервиса.

В какой-то момент, например, по клику пользователя вызывается метод компонента initServerCall. В котором может быть дополнительный код, например, чтобы показать прелоадер. И основное — вызов метода сервиса serverCall.

Осуществляется http запрос к серверу и подписка на его ответ.

Когда ответ получен, можно выполнить какие-то действия, например, response.json() и предварительно отфильтровать результат ответа, a потом вызвать someServerResponse.next() для передачи события дальше.

При этом в примере передается response, но можно передать тот же результат предварительной фильтрации.

3 Comments
  1. Nika
    • Nika
      • shrewmus

Leave a Reply

Your email address will not be published. Required fields are marked *