I have a problem with HTTP requests on Angular5. I have two components (" LoginComponent ", " WellcomeComponent ") and one service (" AuthService ").
I am using auth servise to handle HTTP requests , and also this service is a bridge between two components.
I can do get and post requests from service , but can't use results properly, because of Observable things. I am not an experienced Angular developer so can't find a solution.
So now , I am explaining step by step. I will write all my code here, and all steps are signed by ..Step_ text in code, so you can follow all steps by this sign.
LoginComponent
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../../auth.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent {
loginUserData = {}
constructor(
private _auth: AuthService,
public router:Router ){
//SOMETHING
}
//CLICK FORM SUBMIT BUTTON
public onSubmit(values:Object):void {
//SET USER DATA WITH FORM VALUES
console.log("LoginStep_1 - Hello")
this._auth.getToken(this.loginUserData)
// CHECK TOKEN
// IF VERIFIED
console.log('LoginStep_2 - Token Verified');
this._auth.setUserData(this.loginUserData['username']);
console.log('LoginStep_3 - SetUserData Finished');
this.router.navigate(['/wellcome'])
console.log("LoginStep_4 - Navigated");
}
}
AuthService
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
@Injectable()
export class AuthService {
private _tokenUrl = "http://localhost:8000/api/auth/token/";
private getUserInfoUrl = "http://127.0.0.1:8000/api/userInfo/?username="
private userInfo : any;
constructor(
private http: HttpClient,
private _router: Router
) { }
getToken(user){
console.log("getToken_Step1 - Hello");
this.http.post<any>(this._tokenUrl, user)
.subscribe(
res => {
//getToken_Step2 : SET TOKEN SOMEWHERE
console.log("getToken_Step2 - Token : ", res.token);
},
err => console.log(err)
);
console.log("getToken_Step3 - Bye");
}
setUserData(userName){
console.log("setUserData_Step1 - Hello");
this.http.get<any>(this.getUserInfoUrl+userName)
.subscribe(
res=>{
//setUserData_Step2 : SET USERINFO SOMEWHERE
console.log("setUserData_Step2 - User Info : ", res);
},
err=>{
console.log(err);
}
)
console.log("setUserData_Step3 - Bye");
}
getUserData(){
console.log("getUserData_Step1 - Hello");
return this.userInfo;
}
}
WellcomeComponent
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../../../auth.service';
@Component({
selector: 'app-wellcome',
templateUrl: './wellcome.component.html',
styleUrls: ['./wellcome.component.scss'],
})
export class WellcomeComponent implements OnInit {
constructor(private _auth: AuthService){ }
ngOnInit() {
console.log("Wellcome_Step1 - Hello");
let userInfo = this._auth.getUserData();
console.log("Wellcome_Step2 - Show User Info");
}
}
If you look codes, there are a lot of console.log("Step.. , I am explaining what I want to do by using them.
In a short way, I can say I want to see them at this order in console screen :
These steps are what I want to see on console log screen but, I can't see them with right order. My console output is very different from my expect. Because I don't know how to use angular 5 observable , so can't handle returned value from API.
My console output something like that :
- LoginStep_1- Hello
- LoginStep_3 - SetUserData Finished
- getToken_Step1 - Hello
- getToken_Step2 - Token
... Here, why this order ? How can I correct it ?
So now , How can I do this ? I want to take token and user info by LoginComponent and use them from WellCome component.
As I said, I am not an experienced coder, so maybe solution is very simple but couldn't find.
Thank you for your helps.
Because your requests to backend is asynchronous, it will take time to execute. Therefore, Angular will move on to other tasks: console.log('LoginStep_2 - Token Verified');
and console.log('LoginStep_3 - SetUserData Finished');
before the getToken()
and setUserData()
finished.
You can move subscribe to component
In your AuthService
getToken(user){
console.log("getToken_Step1 - Hello");
return this.http.post<any>(this._tokenUrl, user)
// subscribe moves to component
}
In your component
this._auth.getToken(this.loginUserData)
.subscribe(
res => {
//getToken_Step2 : SET TOKEN SOMEWHERE
console.log("getToken_Step2 - Token : ", res.token);
},
err => console.log(err)
)
Basically, you should implement your function call to return either promise
or observable
(aka async). The AuthService
is something like this (adapted from your question):
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Observable, of} from 'rxjs';
@Injectable()
export class AuthService {
constructor(private http: HttpClient) {}
// private _tokenUrl = "http://localhost:8000/api/auth/token/";
// This is just a mock URL that returns a response (200 OK)
private _tokenUrl =
"https://bikewise.org:443/api/v2/incidents?page=1&proximity_square=100";
// private getUserInfoUrl = "http://127.0.0.1:8000/api/userInfo/?username=";
private userInfo: any;
// can improve with getter/setter instead of exposing directly
private isLoggedIn: boolean = false;
isLoggedInObservable: Observable<boolean>;
getToken(user): Promise<any> {
console.log("getToken_Step1 - Hello");
return new Promise(resolve => {
// this.http.post<any>(this._tokenUrl, user)
// fake request to make sure always get a response
this.http.get<any>(this._tokenUrl)
.subscribe(
res => {
// getToken_Step2 : SET TOKEN SOMEWHERE
console.log("getToken_Step2 - Token : ", "token_1234");
console.log("getToken_Step3 - Bye");
// resolve(res.token);
resolve("token1234");
},
err => {
console.log(err);
throw new Error('Unauthorized...');
});
})
}
setUserData(userName) {
console.log("setUserData_Step1 - Hello");
// If this is a real request, make sure to implement a promise/observable
// return
// this.http.get<any>(this.getUserInfoUrl + userName)
// setUserData_Step2 : SET USERINFO SOMEWHERE
console.log("setUserData_Step2 - User Info : ");
console.log("setUserData_Step3 - Bye");
this.isLoggedIn = true;
this.isLoggedInObservable = of(true);
}
getUserData() {
console.log("getUserData_Step1 - Hello");
return this.userInfo;
}
logOut() {
this.isLoggedInObservable = of(false);
this.isLoggedIn = false;
}
isLogged(): boolean { return this.isLoggedIn; }
}
You also need to setup a AuthGuard
for your routing to track whether user is logged in or not.
Here is a working example stackblitz . Open console to track status
Furthermore, you can always cache your user login status in browser localStorage
to get better user experience. Again, this is adapted from your code. There are many things can be improved from your code. Let me know if you have further questions.
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.