Как запросить асинхронность по интервалу с помощью rxjs в Angular 2



Я хочу задать интервал в http-запросе с помощью rxjs. Мне нужно отправить данные на сервер через n секунд после завершения запроса.



Observable.interval(10000)
.?(() => {
//request for server. return Observable
return this.getData();
})
.subscribe(() => {
console.log("Request done. After 10 second will be next request");
});


Обновление на основе .expand(), предложенное Марком





ngOnInit() {
this.getData()
.expand(() => Rx.Observable.timer(10 * 1000)
.concatMap(() => this.getData())
)
.subscribe(data => {
console.log('received new data', data);
});
}

private getData() {
return Observable.timer(5000)
.do(() => console.log("timer"));
}
577   3  

3 ответов:

Ваш usecase-отличный случай для оператора .expand, который может рекурсивно выполнять и возвращать новые значения. Смотрите этот фрагмент, в котором я добавил много timestamp + debug logging, чтобы прояснить, что происходит.

function getData() {
  // simulate remote call which can take some time
  return Rx.Observable.of('')
    .timestamp()
    .do(i => console.log(`[debug] Going to fetch data from server @${i.timestamp}`))
    .map(i => 'the new JSON blob of data to use') // this would be your actual http.get call
    .delay(1500)
    .timestamp()
    .do(i => console.log(`[debug] Data retreived from server @${i.timestamp}`));
}

getData()
  .expand(_ => Rx.Observable.of('') // we need something to delay upon
    .timestamp()
    .do(i => console.log(`[debug] Waiting 1sec for next getData ${i.timestamp}`))
    .delay(1000)
    .concatMap(() => getData())
  )
  .take(5)
  .subscribe(val => console.log(`New data received @${val.timestamp} : ${val.value}`))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.3/Rx.js"></script>
Таким образом, первоначально вы подписываетесь на getData() и расширяете его значение до рекурсивного delay в течение времени, прежде чем получить следующий getData(). Ни один субъект не участвует в этом подходе, и Ваша подписка остается доступной для получения нового ценности.

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

Убедитесь, что вы импортировали import {Observable} из 'rxjs/Rx' если вы не импортируете его, мы получаем observable not found error иногда

Рабочая plnkr http://plnkr.co/edit/vMvnQW?p=preview

import {Component} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/Rx';
import {Observable} from 'rxjs/Rx';

@Component({
    selector: 'app',
    template: `
      <b>Angular 2 HTTP request every 5 sec RxJs Observables!</b>
      <ul>
        <li *ngFor="let doctor of doctors">{{doctor.name}}</li>
      </ul>

      `
})

export class MyApp {
  private doctors = [];

  constructor(http: Http) {
    Observable.interval(5000)
    .switchMap(() => http.get('http://jsonplaceholder.typicode.com/users/')).map((data) => data.json())
        .subscribe((data) => {
          this.doctors=data; 
           console.log(data);// see console you get output every 5 sec
        });
  }
}

Смотрите Google inspect console вы будете получать новые данные каждые 5 секунд

Я прочитал комментарии, которые вы поместили в этом удаленном ответе. Вы хотите отправить запрос, затем через 10 секунд после получения ответа отправьте другой запрос.

Это довольно сложная, но выполнимая... Я думаю, что что-то вроде этого должно сработать:

let responseSubject = new Rx.BehaviourSubject({});
responseSubject
    .delay(10000)
    .flatMap(() => {
        return http.get(...)
    })
    .subscribe((res) => {
        responseSubject.onNext({});
        // Your stuff here
    });

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

Edit: я что-то упускаю... первая просьба пройдет 10 секунд, прежде чем он начнется. Тогда я бы переписал как:

let responseSubject = new Rx.ReplaySubject(1);
responseSubject
    .delay(10000)
    .startWith({})
    .flatMap(() => {
        return http.get(...)
    })
    .subscribe((res) => {
        responseSubject.onNext({});
        // Your stuff here
    });

Comments

    Ничего не найдено.