Повторно вызывайте REST в Angular (5)

Мне нужно создать службу, которая будет потреблять данные из службы ожидания с длительным опросом в моем бэкэнде. Когда я вызываю эту службу, бэкэнд ждет, пока у него не будет данных для отправки или истечет время ожидания, и отправит только пустой объект.

В angular мне нужна служба, которая запускается, когда приложение полностью загружено, и будет работать в фоновом режиме и передавать данные субъектам, которые я наблюдаю.

Можете сказать мне, как лучше всего или показать мне пример, как должен выглядеть этот сервис в angular?

Вот моя попытка, но она не вызывает отдых при запуске:

@Injectable()
export class PollingService {

  private url: string;

  constructor(private http: HttpClient, private fooService: FooService) {
    this.url = 'http://localhost:8080/api/poll';
    this.startPolling();
  }

  startPolling() {
    this.http.get<any>(this.url)
      .map(pollData => {
        console.log('poll data', pollData);
        this.fooService.mySubject.next(pollData);
        if (pollData)
          this.startPolling();
      });
  }
}

person Denis Stephanov    schedule 11.05.2018    source источник
comment
Вы пробовали Observable.timer(0, 5000). Звонки каждые 5 секунд.   -  person User3250    schedule 11.05.2018
comment
Когда вы говорите, что время ожидания истекло и отправляете только пустой объект, это только для первой попытки или для всех попыток?   -  person bygrace    schedule 11.05.2018
comment
Вы действительно хотите начать запрашивать данные о загрузке приложения или предпочитаете подождать, пока не узнаете, что что-то в вашем приложении требует этого? Если это основано на подписке, вы не будете использовать API, пока никому не нужны данные.   -  person bygrace    schedule 11.05.2018
comment
@User3250 User3250 Я не могу использовать это, потому что у меня есть логика на бэкэнде ... запрос завершается, когда на сервере есть новые данные или время истекло. Таким образом, запрос может занять любое время от 1 до X секунд.   -  person Denis Stephanov    schedule 11.05.2018
comment
@bygrace это для всех.   -  person Denis Stephanov    schedule 11.05.2018
comment
@bygrace да, мне нужно запрашивать сервер, пока пользователь не закроет приложение или не выйдет из системы.   -  person Denis Stephanov    schedule 11.05.2018
comment
Тайм-аут короче или равен интервалу опроса?   -  person bygrace    schedule 11.05.2018
comment
@bygrace проверьте мой код, пожалуйста. Я указываю, что хочу снова вызвать службу, когда получу результат предыдущего запроса. if (recivedData) { // делаем что-то и снова вызываем этот метод }   -  person Denis Stephanov    schedule 11.05.2018


Ответы (2)


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

Рабочий пример может выглядеть так:

startPolling() {
    this.http.get<any>('url').subscribe((pollData) => {
        console.log('poll data', pollData);
        this.fooService.mySubject.next(pollData);
        if (pollData)
          this.startPolling();
    }, (error) => {
        console.log(error);
        // stop poll or use exponential backoff polling
    })

Однако длинный опрос HTTP в настоящее время является посредственным с такими концепциями, как отправка сервера, один из способов их реализации — через веб-сокеты.

person Joshua Chan    schedule 11.05.2018
comment
Не знаю, почему кто-то дал этому ответу большой палец вниз, полностью согласен. Кроме того, он также прав в том, что необходимо подписаться, чтобы запрос действительно сработал. - person enf0rcer; 11.05.2018
comment
@ enf0rcer Длинный опрос — хорошо известная техника. Он устарел во времена WebSockets, но по-прежнему актуален для устаревших систем и когда вы не можете быстро внедрить новую сессионную архитектуру (что довольно сложно, когда речь идет о масштабируемости). Также не важно, когда вы делаете карту - до или после подписки. - person Phil; 11.05.2018
comment
@Phil, спасибо за отзыв, я постараюсь лучше изучить вопрос, прежде чем отвечать в следующий раз. - person Joshua Chan; 11.05.2018

Ваш PollingService должен сосредоточиться только на HTTP-запросе и позволить любым компонентам вызывать его.

@Injectable()
export class PollingService {

    url: string;

    constructor(private http: HttpClient, private fooService: FooService) {}

    startPolling() {
        this.url = 'http://localhost:8080/api/poll';
        return this.http.get<any>(this.url);
    }
}

Ваш компонент:

export class YourComponent implement OnInit{

constructor(private pollingService : PollingService,
            private fooService : FooService){}

theMethodYouWantToConsumeTheService(){
    this.pollingService.startPolling().subscribe(
        //If success
        (pollData) => {
            console.log('poll data', pollData);
            this.fooService.mySubject.next(pollData);
        },
        //If error
        (error)=>{
            console.log(error);
        }
    );
    }
}
person Ryan Huang    schedule 11.05.2018
comment
Я не хочу предоставлять услугу опроса вызовов для любого компонента. Это должен быть независимый сервис, который будет вызывать REST и ждать ответа, а когда ответ будет получен, он обновит некоторые локальные данные по сервисам и вызовет другой запрос. Компоненты будут просто подписываться на эти данные, которые будут изменены службой опроса, а не самой службой опроса. - person Denis Stephanov; 11.05.2018