2
\$\begingroup\$

Just started to use rxjs few weeks ago, I think I'm getting most of it right, but my code seems to be not that efficient and prone to bugs I haven't run into yet!

I need to be able to send http requests my app is online(1) and when the user is authenticated(2) and when there's anything to send(3). I'm pretty sure there's a smart way to combine those 3 conditions the "rxjs" way :)

SuperHttpRequest

class SuperHttpRequest extends HttpRequest<any> {

  _id: string; // Used for localStorage

  constructor(method: string, url: string, body: any, _id?: string) {
    super(method, url, body);
    this._id = _id || UUID.UUID();
  }
}

HttpRequestHandler

@Injectable()
class HttpRequestHandler extends ReplaySubject<SuperHttpRequest> {

  nbItemsInQueue$: ReplaySubject<Number>; // Needed by a component (sync progress), would be better to use the combined http request time
  private requests: SuperHttpRequest[];
  private requestsSubcription: Subscription;

  constructor(
    private network: Network, // Ionic service
    private http: HttpClient,
    private localStore: LocalStore<SuperHttpRequest[]>,
    private authService: AuthenticationService) {

    super();

    this.requests = [];
    this.nbItemsInQueue$ = new ReplaySubject(this.requests.length);

    this.localStore.get('http-request')
      .then(requests => {
        if (requests) {
          requests.forEach(request => {
            this.next(new SuperHttpRequest(request.method, request.url, request.body, request._id));
          });
        }
      });

    this.nbItemsInQueue$
      .subscribe(() => this.localStore.set('http-request', this.requests));

    this.authService.currentUser$
      .subscribe(user => {
        if (!user) { if (this.requestsSubcription) { this.requestsSubcription.unsubscribe(); } }
        else {
          this.requestsSubcription = this
            .takeWhile(() => {
              if (navigator.onLine) { return true; }
              else { throw Error(); }
            })
            .retryWhen(() => this.network.onConnect())
            .subscribe(request => this.handleHttpRequest(user, request));
        }
      });
  }

  private handleHttpRequest(user: Credentials, request: SuperHttpRequest) {
    this.http.request(request.clone({ setHeaders: { Authorization: `Bearer ${user.token}` } }))
      .retryWhen(error => {
        return error
          .mergeMap((error: any) => {   
            if (error.status === 503) {
              return of(error.status).delay(2000)
            }
            return Observable.throw({ error: 'No retry' });
          })
          .take(5)
          .concat(Observable.throw({ error: 'Sorry, there was an error (after 5 retries)' }));
      })
      .subscribe(res => {
        if (res instanceof HttpResponse) {
          remove(this.requests, (req) => req._id === request._id);
          this.nbItemsInQueue$.next(this.requests.length);
        }
      });
  }

  next(request: SuperHttpRequest) {
    this.requests.push(request);
    this.nbItemsInQueue$.next(this.requests.length);
    super.next(request);
  }

}
\$\endgroup\$

1 Answer 1

-1
\$\begingroup\$
//Maintain Queue of http Observable
const quequeHTTP = [];

//Dummy Http Request
getData(){
   return this.http.get('./api');
}

addInQueuqe(observable:Observable<any>){
     quequeHTTP.push(observable);
}

//Dummy addition 4 request
addInQueuqe(this.getData());
addInQueuqe(this.getData());
addInQueuqe(this.getData());
addInQueuqe(this.getData());

eventWhenXHappen(){
  Observable.forkJoin(quequeHTTP).subscribe((resArr)=>{
     console.log('When all request succesfully executed ');
},(err)=>{
  console.log('When error occur');
})


}
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Review! You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer. \$\endgroup\$ Commented Feb 11, 2021 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.