Confusion in subscribe


#1

I am new to Angular and ionic and i am confused a little.

So i have auth.service.ts and profile.ts, auth.service takes care of http api part. profile.ts is a component for a page.

    public authenticated() {
        return tokenNotExpired();
    }

    getProfile() {
        this.authHttp.get(`${this.config.apiUrl}/me/`, { headers: this.contentHeader })
            .map(res => res.json())
            .subscribe(
                data => this.local.set('profile', JSON.stringify(data))
            )
            // .catch(this.handleError);
    }

    login(credentials) {
        return this.http.post(`${this.config.apiUrl}/auth/login/`, JSON.stringify(credentials), { headers: this.contentHeader })
            .map(res => res.json())
            .map(data => { // <<--------- is this correct way?
                    console.log(data);
                    this.user = this.getProfile();
                    return data;
                }
            )
            .catch(this.handleError);
    }

now i can subscribe to the auth.service -> login() function from profile.ts

profile.ts

onLogin(form) {
        this.submitted = true;
        if (form.valid) {
            this.auth.login(form.value).subscribe(
                data => {
                    this.auth.authSuccess(data.token);
                    this.nav.push(TabsPage);
                },
                err => this.error = 'Unable to login with provided credentials.'
            );
        }
    }

is this the right way? please let me know.

thanks


#2

There are a few things incorrect here. For example, you don’t need to use subscribe in your requests.

getProfile() {
  return this.authHttp.get(`${this.config.apiUrl}`/me/, { 
    headers: this.contentHeader 
  })
    .map(res => res.json())
}

You don’t need to subscribe there, you just need to return a value from the request.

Then for the call to the service in your component class, you’re almost there, just need to wrap the data in parens

onLogin(form) {
  this.submitted = true;
  if (form.valid) {
    this.auth.login(form.value).subscribe(
      (data) => {
        this.auth.authSuccess(data.token);
        this.nav.push(TabsPage);
      },
      (err) => this.error = 'Unable to login with provided credentials.'
    );
  }
}

#3

So basically i cannot getProfile() within login(credentials) function in auth.service? what if i dont need to do that on page side… what if i want to do it within auth.service.ts?


#4

It’s not clear to me whether the two functions getProfile and login have data dependencies on one another, or whether you want to cache the responses or always be hitting the backend. Those are important concerns for the final recommended solution, but the biggest thing I can say at this point is that I think it’s a mistake to do things inside observable map chains that modify state, such as your assignment to this.user and presumably the call to this.local.set. Map chains are for transforming the data into a format that callers prefer. Both getProfile and login should be returning observables of some type and not modifying anything internal. Once that’s done, then there’s no problem with them calling one another if that’s still what you really want to do. You can chain the observables with the flatMap operator.


#5

For example, i want to schedule refresh token on login.

where to put this part

    // Schedule a token refresh
    this.scheduleRefresh();

in

    login(credentials) {
        return this.http.post(`${this.config.savelife.apiUrl}/auth/login/`, JSON.stringify(credentials), { headers: this.contentHeader })
            .map(res => res.json())
            .catch(this.handleError);
    }

#6

Either put it before the call to http, or subscribe to the observable you are returning from login and do it then.


#7

So basically services are just for http crud operations with map and catch error chain functions. Thats the purpose of a service? And a component will use the data service, process it and display as need. Please correct if im wrong. Im trying to find the best practices. Thanks