Crowdpleasr
Crowdpleasr

Reputation: 4044

Why is Observable within Observable hanging?

I have an http.get call in my service member.service.ts and I want to wait until that call completes before proceeding in app.component, so I'm trying to wrap the http.get call into an Observable for processing in app.component.

[Note: previously, before I wrapped the service in an Observable, the service was working fine . . . the http.get call on its own works as expected and returns a JSON object.]

But when I wrapped the http.get call in an Observable, as below, the application hangs. I searched online and read about flatMap, forkjoin, etc., but I'd like to keep the current structure, where the http.get call is in the member service, and all the other code is in app.component.

Many thanks if any ideas why it's hanging and how to fix!

member.service.ts

import { Injectable } from '@angular/core';
import { Observable, from, of } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class MemberService {
  url: string = "http://localhost:3000/sign-up";
  data: string = '';

  constructor(private http: HttpClient) { }

  getMemberForm(): Observable<any> {

   let library = this.http.get(this.url,{responseType: 'json'});

    library.subscribe((data) => {
      this.data = JSON.stringify(data);
    });
    return of(this.data);
  }

}

app.component.ts

import { Component, OnInit, Injectable } from '@angular/core';
import { MemberService } from './member.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

@Injectable()
export class AppComponent implements OnInit {
  got_data: boolean = false;
  data: string;

  constructor(private member: MemberService) {}

  ngOnInit() {

    this.member.getMemberForm().subscribe((data)=>{
      this.data = data;
      if (this.data.length > 0) this.got_data = true; 
    });
  }

}

Upvotes: 1

Views: 775

Answers (2)

Vash72
Vash72

Reputation: 622

Never subscribe in a service this is a "anti pattern" in reactive programming (rxjs), just create the observable(http call) in the service and than subscribe in you component to trigger the http request, {responseType: 'json'} isn't needed all the "latest" versions (>4.3) of angular http client do it by default

interface MyDataType{
    data: any;
}

 getMemberForm() {
   //no need to type the function return beacuse typescript will do it for you
   //you can type directly the http call
   return this.http.get<MyDataType>(this.url);

  }

Upvotes: 1

asimhashmi
asimhashmi

Reputation: 4378

You are not handling the asynchrous code in a proper way.

Asynchronous code is the code which runs outside the normal execution flow of code. The code inside your subscribe method is asynchronous and it will only run when the response of HTTP call is received.

Change your code like this:

getMemberForm(): Observable<any> {

   return this.http.get(this.url,{responseType: 'json'})
    .pipe(map( res => of(JSON.stringify(res))))    
  }

You application is hanging probably because your this.data is undefined and your are trying to change undefined into Observable

Upvotes: 2

Related Questions