Angular variable assign value if/else inside subscribe getting undefined

here is my complete code function example:

public scan(formData: Object): Observable<any> {

let url = this.remoteUrl;


let result;
this.onlineService.isOnline$.subscribe( (isOnline) => {
  if (isOnline) {

    console.log('services is online connected');
    
    result = this
    ._http
    .post(url, formData, { headers: headers })
    .pipe(map((res: any) => {
      // console.log(res);

      let response = res;
      return response;
    }),
      catchError(error => {
        if (error.status === 401 || error.status === 403) {
          // handle error
        }
        return throwError(error);
      }));

  }else{

    console.log('services are offline');

    result = this.dbService.getByIndex('safety', 'code', formData['trafoStation']).subscribe( (location) => {
      return location;
    });

  }

});
console.log(result);

return result;
};

actually, I need to run two different services based on an internet connection if the connection is available then call server API otherwise store on offline ngx-indexed-db.

i have stored data both online and offline.

getting undefined in result.

Answer

Result is undefined because it’s an async operation: this.onlineService.isOnline$ has not emmited yet, but you already have return result, thus the undefined.

Also, the way you combine your observables is not right. You should NOT create new observables (and subscribe to them) in a subscribe method. That lead to weird side effects and memory leaks down the line.

Here’s my proposal to get your code to work. I used the switchMap operator to return either your apiCall or your store operation based on isOnline$ value. SwitchMap is used to combine a higher observable with an inner observable and flatten the stream. It will also interupt the current subscription each time isOnline$ emits:

private _handleServices(formData, isOnline: boolean): Observable<any> {
    console.log(`services are ${isOnline ? 'online': 'offline'}`);
    const url = this.remoteUrl;
    const apiCall$ = this._http.post(url, formData, { headers: headers })
      .pipe(
        catchError(error => {
          if (error.status === 401 || error.status === 403) {
            // handle error
          }
          return throwError(error);
        })
      );
   const store$ = this.dbService.getByIndex('safety', 'code', formData['trafoStation']);
   return (isOnline) ? apiCall$ : store$;
}

public scan(formData: Object): Observable<any> {
  return this.onlineService.isOnline$.pipe(
    switchMap((isOnline) => this._handleServices(formData, isOnline)),
    tap(res => console.log(res))
  );
};

Then, when you call your function in your component, you will call it like this:

this.scan(formData).subscribe(res => /* handle scan response */);