简体   繁体   中英

How to Request Async by interval using rxjs in Angular 2

I want to set interval in http request using rxjs. I need to send data on server from n seconds after request finish.

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

UPDATE based on .expand() suggested by Mark

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"));
}

i think you want to request server for something every few seconds. can you try this way

make sure you have imported import {Observable} from 'rxjs/Rx' if you don't import it we get observable not found error sometimes

working 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
        });
  }
}

see google inspect console you will be getting new data every 5 sec

Your usecase is an excellent case for the .expand operator which can recursively execute and return new values. See this snippet in which i have added a lot of timestamp + debug logging to clarify what is going on.

 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> 

so initially you subscribe to the getData() and expand its value to recursively delay for time before retrieving the next getData() . No subjects are involved in this approach and your subscription stays available for receiving the new values.

I've read the comments you put in that deleted answer. You want to send a request, then 10 seconds after receiving a response send another request.

That's quite complex, but doable... I think something like this should work:

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

Here I'm setting up a behaviour so I can feedback when we get a response. Then setup a stream that after 10 seconds of a request, it makes the request and yields the response.

Edit: I'm missing something... the first request will take 10 seconds before it starts. Then I would rewrite as:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM