简体   繁体   中英

Subscribe to observable after http call. Angular 6

this is an issue I'm having in Angular. The below method makes two http calls.

  submit(username: string, pword: string) {
    this.loginService.signIn(username, pword);

    this.loginService.currentloginAttemp.subscribe(data => {
      if (data == true) {
        this.profileService.getProfile();    
      }
    });

    this.profileService.newProfileObj.subscribe(dataProfile =>{
      console.log(dataProfile);
    });
  }

  submit(username: string, pword: string) {
    this.loginService.signIn(username, pword);

signIn makes an http call and assigns to an observable called currentloginAttemp

    this.loginService.currentloginAttemp.subscribe(data => {
      if (data == true) {
        this.profileService.getProfile();    
      }
    });

The above code works without any problems. this.profileService.getProfile() makes an http call to obtain a new Profile. The below code subscribes to that profile that was obtained.

    this.profileService.newProfileObj.subscribe(dataProfile =>{
      console.log(dataProfile);
    });
  }

When I do console.log(dataProfile); I get an undefined warning.

When I run this function:

  logout() {
        this.profileService.newProfileObj.subscribe(dataProfile =>{
          console.log(dataProfile);
        });
  }

console.log(dataProfile) returns a profile.

How do I delay after the line of code this.profileService.getProfile() so that when I subscribe to the profile, my component will see it?

EDIT:

Just to be clear. currentloginAttemp is assigned when this.loginService.signIn makes an http call. Which is why I'm not sure why newProfileObj is null when it is assigned in the method this.profileService.getProfile().

EDIT 2:

  getProfile() {
    let tempURL = this.getProfileUrl + this.currProfileId.value;
    this.http.get<Profile>(tempURL).subscribe((data) => {
      this.currProfileObj.next(data);
    });
  }

Your issue is that you are using a BehaviorSubject and it is emitting immediately, as well as each time you issue .next(). See docs on how BehaviorSubject works here . Because of this, you'll often want to skip that first emission because you really only care about the rest of them. In your case that would look something like this (in rxjs 6+):

this.profileService.newProfileObj.pipe(skip(1)).subscribe(dataProfile =>{
  console.log(dataProfile);
});

This is a solution. But, I'm not sure if it's the best solution.

Inside my component I created a function:

  async delay(ms: number) {
    return new Promise( resolve => setTimeout(resolve, ms) );
  }

After making the second http call I called the async functino from above ^:

    (async () => { 
      // Do something before delay
      console.log('before delay')

     await this.delay(2000);
      this.profileService.newProfileObj.subscribe(dataProfile =>{
        console.log(dataProfile);
      // Do something after
      console.log('after delay')
  })();

This worked, although I'm not sure if it's the best solution.

I think you are using subject. You should use BehaviorSubject instead of subject. A subject doesn't hold a value.

Subject example:

const subject = new Rx.Subject();
subject.next(1);
subject.subscribe(x => console.log(x));

Console output will be empty

BehaviorSubject example:

const subject = new Rx.BehaviorSubject();
subject.next(1);
subject.subscribe(x => console.log(x));

Console output: 1

BehaviorSubject can be created with initial value: new Rx.BehaviorSubject(1)

You can also try this if you don't want to use above method.

 this.profileService.newProfileObj.subscribe(dataProfile =>{
        if (dataProfile) {
            console.log(dataProfile);
          }   
        });
  }
getxTaskXCall()
     getxTask()
      .subscribe(
        success => {
         processFn(success);
        },
        error => {
          // this.errors = error;
        },
        () => {

        }
      );
       getxTask(tId: string, parameters: Array<number>): Observable<[string]> {
        return this.apiService.get(getUrl + tId + '/' + parameters)
            .pipe(map(data => data));
    }

 get(path: string, params: HttpParams = new HttpParams()): Observable<any> {
    return this.http.get(`${api_url}${path}`, { params })
      .pipe(catchError(this.formatErrors));
  }

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