[英]Angular5 How to use Http Observable
I have a problem with HTTP requests on Angular5. 我在Angular5上遇到HTTP请求问题。 I have two components (" LoginComponent ", " WellcomeComponent ") and one service (" AuthService ").
我有两个组件(“ LoginComponent ”,“ WellcomeComponent ”)和一个服务(“ AuthService ”)。
I am using auth servise to handle HTTP requests , and also this service is a bridge between two components. 我正在使用auth servise处理HTTP请求,并且此服务也是两个组件之间的桥梁。
I can do get and post requests from service , but can't use results properly, because of Observable things. 由于可以观察到的事情,我可以从service获取和发布请求,但不能正确使用结果。 I am not an experienced Angular developer so can't find a solution.
我不是经验丰富的Angular开发人员,所以找不到解决方案。
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.
我将在此处编写所有代码,所有步骤均由代码中的..Step_文本签名,因此您可以按照此符号执行所有步骤。
LoginComponent
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. 如果您看代码,会有很多console.log(“ Step .. ,我正在解释我想通过使用它们来做什么。
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.
因为我不知道如何使用angular 5 observable,所以无法处理API返回的值。
My console output something like that : 我的控制台输出类似这样的内容:
- LoginStep_1- Hello
LoginStep_1-您好
- LoginStep_3 - SetUserData Finished
LoginStep_3-SetUserData完成
- getToken_Step1 - Hello
getToken_Step1-您好
- getToken_Step2 - Token
getToken_Step2-令牌
... 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.
我想通过LoginComponent获取令牌和用户信息,并从WellCome组件中使用它们。
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');
因此,Angular将继续执行其他任务:
console.log('LoginStep_2 - Token Verified');
and console.log('LoginStep_3 - SetUserData Finished');
和
console.log('LoginStep_3 - SetUserData Finished');
before the getToken()
and setUserData()
finished. 在之前
getToken()
和setUserData()
完成。
You can move subscribe to component 您可以移动订阅组件
In your AuthService 在您的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). 基本上,您应该实现函数调用以返回
promise
或observable
(又称异步)。 The AuthService
is something like this (adapted from your question): AuthService
如下所示(根据您的问题进行了修改):
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. 您还需要为路由设置
AuthGuard
,以跟踪用户是否登录。
Here is a working example stackblitz . 这是一个工作示例stackblitz 。 Open console to track status
打开控制台以跟踪状态
Furthermore, you can always cache your user login status in browser localStorage
to get better user experience. 此外,您始终可以将用户登录状态缓存在浏览器
localStorage
以获得更好的用户体验。 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.
如果您还有其他问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.