首页 文章

Angular5如何使用Http Observable

提问于
浏览
0

我对Angular5上的HTTP请求有问题 . 我有两个组件(“ LoginComponent ", " WellcomeComponent ") and one service (" AuthService ”) .

我使用auth servise来处理HTTP请求,而且这个服务是两个组件之间的桥梁 .

我可以从服务获取和发布请求,但由于Observable事情,无法正确使用结果 . 我不是一位经验丰富的Angular开发人员,因此无法找到解决方案 .

所以现在,我正在逐步解释 . 我将在此处编写所有代码,并且所有步骤都由代码中的 ..Step_ 文本签名,因此您可以按照此符号执行所有步骤 .


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");
    }

}

如果你看代码,有很多 console.log("Step.. ,我正在解释我想用它们做什么 .

简而言之,我可以说我想在控制台屏幕上按此顺序查看它们:

  • LoginStep_1 - 您好:单击表单上的提交按钮可以执行此步骤

  • getToken_Step1 - 您好:转到身份验证服务

  • getToken_Step2 - 令牌:从API获取令牌并将其写入localStorage

  • getToken_Step3 - 再见

  • LoginStep_2 - Token已验证:然后返回并验证此令牌 .

  • setUserData_Step1 - 您好

  • setUserData_Step2 - 用户信息:从API获取用户信息并将其写入localStorage

  • setUserData_Step3 - 再见

  • LoginStep_3 - SetUserData完成:我得到了令牌,验证了它,得到了用户信息并写了它 . 所以我现在可以去导航了 .

  • Wellcome_Step1 - 您好:从登录导航

  • getUserData_Step1 - Hello:获取LoginComponent编写的所有信息

  • Wellcome_Step2 - 显示用户信息:使用用户信息执行您想要的操作

这些步骤是我想在控制台日志屏幕上看到的,但我看不到正确的顺序 . 我的控制台输出与我的预期非常不同 . 因为我不知道如何使用angular 5 observable,所以无法处理来自API的返回值 .

我的控制台输出类似的东西:

LoginStep_1- Hello LoginStep_3 - SetUserData完成getToken_Step1 - Hello getToken_Step2 - Token

......在这里,为什么这个订单?我该如何纠正?


所以现在,我该怎么做?我想通过LoginComponent获取令牌和用户信息,并从WellCome组件中使用它们 .

正如我所说,我不是一个经验丰富的编码员,所以也许解决方案很简单但找不到 .

谢谢你的帮助 .

2 回答

  • 0

    因为您对后端的请求是异步的,所以执行它需要时间 . 因此,Angular将继续执行其他任务: console.log('LoginStep_2 - Token Verified');console.log('LoginStep_3 - SetUserData Finished'); ,然后 getToken()setUserData() 完成 .

    您可以移动订阅组件

    在您的AuthService中

    getToken(user){
            console.log("getToken_Step1 - Hello");
    
            return this.http.post<any>(this._tokenUrl, user)
            // subscribe moves to component
        }
    

    在您的组件中

    this._auth.getToken(this.loginUserData)
      .subscribe(
        res => {
    
          //getToken_Step2 : SET TOKEN SOMEWHERE
          console.log("getToken_Step2 - Token : ", res.token);
        },
        err => console.log(err)
      )
    
  • 0

    基本上,您应该实现函数调用以返回 promiseobservable (也称为异步) . 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; }
    }
    

    您还需要为路由设置 AuthGuard 以跟踪用户是否已登录 .

    这是一个工作示例stackblitz . Open console to track status

    此外,您始终可以在浏览器 localStorage 中缓存用户登录状态,以获得更好的用户体验 . 同样,这是根据您的代码改编的 . 您的代码可以改进很多东西 . 如果您有其他问题,请与我们联系 .

相关问题