簡體   English   中英

Angular5如何使用Http Observable

[英]Angular5 How to use Http Observable

我在Angular5上遇到HTTP請求問題。 我有兩個組件(“ LoginComponent ”,“ WellcomeComponent ”)和一個服務(“ AuthService ”)。

我正在使用auth servise處理HTTP請求,並且此服務也是兩個組件之間的橋梁。

由於可以觀察到的事情,我可以從service獲取和發布請求,但不能正確使用結果。 我不是經驗豐富的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");
    }

}

驗證服務

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

}

惠康組件

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 .. ,我正在解釋我想通過使用它們來做什么。

簡而言之,我可以說我想按以下順序在控制台屏幕中看到它們:

  1. LoginStep_1-您好: 通過單擊表單上的提交按鈕,此步驟將起作用
  2. getToken_Step1-您好: 轉到身份驗證服務
  3. getToken_Step2-令牌: 從API獲取令牌並將其寫入localStorage
  4. getToken_Step3-再見
  5. LoginStep_2-令牌已驗證: 然后返回並驗證此令牌。
  6. setUserData_Step1-您好
  7. setUserData_Step2-用戶信息: 從API獲取用戶信息並將其寫入localStorage
  8. setUserData_Step3-再見
  9. LoginStep_3 -SetUserData完成: 我得到了令牌,對其進行了驗證,獲得了用戶信息並進行了編寫。 所以我現在可以導航。
  10. Wellcome_Step1-您好: 從登錄導航
  11. getUserData_Step1-您好: 獲取LoginComponent編寫的所有信息
  12. Wellcome_Step2-顯示用戶信息: 使用用戶信息執行所需操作

這些是我想在控制台日志屏幕上看到的步驟,但是我無法以正確的順序看到它們。 我的控制台輸出與我的預期有很大不同。 因為我不知道如何使用angular 5 observable,所以無法處理API返回的值。

我的控制台輸出類似這樣的內容:

  1. LoginStep_1-您好
  2. LoginStep_3-SetUserData完成
  3. getToken_Step1-您好
  4. getToken_Step2-令牌

...在這里,為什么要這個命令? 我該如何糾正?


所以現在,我該怎么做? 我想通過LoginComponent獲取令牌和用戶信息,並從WellCome組件中使用它們。

就像我說的,我不是一個有經驗的編碼員,所以也許解決方案很簡單但是找不到。

謝謝您的幫助。

由於您對后端的請求是異步的,因此需要花費一些時間來執行。 因此,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)
  )

基本上,您應該實現函數調用以返回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 打開控制台以跟蹤狀態

此外,您始終可以將用戶登錄狀態緩存在瀏覽器localStorage以獲得更好的用戶體驗。 同樣,這是根據您的代碼改編的。 您的代碼有很多可以改進的地方。 如果您還有其他問題,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM