2017-10-10 5 views
0

J'ai écrit un système d'authentification en angulaire 4 en utilisant la fonction RxJS Observer. L'interrogation de la base de données Oracle est basée sur querystream converti en observateur/observable en service, puis en composant de connexion avec formulaire de connexion je m'abonne à obervable en service pour obtenir le résultat de l'authentification. L'objet observable du service, renvoyé par la méthode, publie "true" ou "false" si l'utilisateur est authentifié ou non. En cliquant sur le bouton de connexion dans le composant du formulaire de connexion, l'animation de chargement est affichée et le formulaire de connexion est caché. Lorsque l'utilisateur est authentifié, le routeur redirige l'utilisateur vers les pages de fonction. Lorsque l'utilisateur n'est pas authentifié, l'animation de chargement est masquée et le formulaire de connexion s'affiche à nouveau. Mais cela ne fonctionne pas comme prévu. Dans la console je vois que la sortie utilisateur n'est pas connecté, et en même temps l'animation de chargement est toujours affiché, la forme est cachée, en dépit des propriétés d'affichage du composant showLoading = false et showLoginForm = truePourquoi la vue angulaire de 4 composants ne se rétracte pas lorsque les propriétés du composant sont modifiées dans les rappels d'abonnement?

login.service.ts

import { Injectable } from '@angular/core'; 
 
import { DbSelectService } from '../db/db-select.service'; 
 
import * as md5 from 'js-md5'; 
 
import { AuthModel, CurrentUserModel } from '../../data-models/data-models.interfaces'; 
 
import { DbSelectQueryParams } from '../../data-models/data-models.interfaces'; 
 
import { CurrentUserDbRow } from '../../data-models/db-responses.interfaces'; 
 
import { SessionService } from '../core/session.service'; 
 
import { CacheService } from '../feature/cache.service'; 
 
import { LoggerService } from '../core/logger.service'; 
 
import { Observable } from 'rxjs/Observable'; 
 
import { Observer } from 'rxjs/Observer'; 
 

 
@Injectable() 
 
export class LoginService { 
 

 
    private currentAuthData: AuthModel; 
 
    private currentUser: CurrentUserModel; 
 

 
    constructor (
 
     private dbSelect: DbSelectService, 
 
     private sessionService: SessionService, 
 
     private cacheService: CacheService, 
 
     private logger: LoggerService 
 
    ) { 
 

 
     this.currentAuthData = this.cacheService.getCurrentAuthDataCache(); 
 
     this.currentUser = this.cacheService.getCurrentUser(); 
 

 
    } 
 

 
    checkAccessRights(): Observable<boolean> { 
 

 
     return new Observable((observer: Observer<boolean>) => { 
 

 
      const queryParams: DbSelectQueryParams = { 
 
       fields: [ 
 
        `NAME`, 
 
        `ROLE` 
 
       ], 
 
       tables: [ 
 
        `SINS.P_USER` 
 
       ], 
 
       conditions: [ 
 
        `UPPER(P_USER.NAME) = UPPER(:username)`, 
 
        `AND`, 
 
        `PSWD = :password`, 
 
        `AND`, 
 
        `HASH = :hash`, 
 
        `AND`, 
 
        `LOCKED <> '1'`, 
 
        `AND`, 
 
        `ROWNUM = 1` 
 
       ] 
 
      }; 
 

 
      const bindParams = { 
 
       username: this.currentAuthData.username, 
 
       password: this.currentAuthData.password, 
 
       hash: md5(this.currentAuthData.password) 
 
      }; 
 

 
      let userIsAuthenticated = false; 
 
      const AUTHENTICATED = true; 
 
      const NOT_AUTHENTICATED = false; 
 

 
      this.dbSelect.select<CurrentUserDbRow>(queryParams, bindParams).subscribe(
 
       user => { 
 

 
        console.warn(user); 
 
        this.currentUser.username = user.NAME.toUpperCase(); 
 
        this.currentUser.role = user.ROLE.toLowerCase(); 
 

 
        this.sessionService.getAccessToUser(); 
 

 
        userIsAuthenticated = true; 
 

 
        observer.next(AUTHENTICATED); 
 
        observer.complete(); 
 

 
       }, 
 
       err => { 
 

 
        observer.error(err); 
 
        this.logger.writeError(err); 
 
        this.sessionService.closeSession(); 
 

 
       }, 
 
       () => { 
 

 
        observer.next(NOT_AUTHENTICATED); 
 
        observer.complete(); 
 

 
        if (userIsAuthenticated === NOT_AUTHENTICATED) { 
 
         this.logger.writeNewError('logon denied'); 
 
         this.sessionService.closeSession(); 
 
        } 
 

 
       } 
 
      ); 
 

 
     }); 
 

 
    } 
 

 

 
}

login.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core'; 
 
import { Title } from '@angular/platform-browser'; 
 
import { AppConfig } from '../services/core/app-config.service'; 
 
import { remote } from 'electron'; 
 
import { LoginService } from '../services/auth/login.service'; 
 
import { AuthModel } from '../data-models/data-models.interfaces'; 
 
import { ToastService } from '../services/core/toast.service'; 
 
import { CacheService } from '../services/feature/cache.service'; 
 
import { AppConfigParamsModel, MaxLengthAndValueModel } from '../data-models/data-models.interfaces'; 
 
import { Subscription } from 'rxjs/Subscription'; 
 

 
@Component({ 
 
    selector: 'login', 
 
    styleUrls: ['app/login/login.component.css'], 
 
    templateUrl: 'app/login/login.component.html' 
 
}) 
 

 
export class LoginComponent implements OnInit, OnDestroy { 
 

 
    private pagename = 'Логин'; 
 
    private showLoading = false; 
 
    private showLoginForm = true; 
 
    private loginSubscription: Subscription; 
 

 
    private authmodel: AuthModel; 
 

 
    private maxlength: MaxLengthAndValueModel = { 
 
     username: 32, 
 
     password: 32 
 
    }; 
 

 
    constructor (
 
     private titleService: Title, 
 
     private config: AppConfig, 
 
     private loginService: LoginService, 
 
     private toastService: ToastService, 
 
     private cacheService: CacheService 
 
    ) { 
 

 
     this.authmodel = this.cacheService.getCurrentAuthDataCache(); 
 

 
    } 
 

 
    ngOnInit() { 
 

 
     this.config.getParams().then((params: AppConfigParamsModel) => { 
 

 
      this.titleService.setTitle(`${params.appname} - ${this.pagename}`); 
 

 
     }); 
 

 
    } 
 

 

 
    ngOnDestroy() { 
 

 
     if (this.loginSubscription) { 
 
      this.loginSubscription.unsubscribe(); 
 
     } 
 

 
    } 
 

 

 
    private onLogin(): void { 
 

 
     this.showLoadingAnimation(); 
 

 
     this.loginSubscription = this.loginService.checkAccessRights().subscribe(
 
      accessAllowed => { 
 

 
       if (accessAllowed) { 
 

 
        this.toastService.showAdviceToast('Добро пожаловать!'); 
 

 
       } else { 
 

 
        this.hideLoadingAnimation(); 
 
        this.toastService.showErrorToastWithAdvice('ВХОД ЗАПРЕЩЁН', 'Обратитесь к администратору'); 
 

 
       } 
 

 
      }, 
 
      err => { 
 

 
       this.hideLoadingAnimation(); 
 
       this.toastService.showErrorToastWithAdvice('Не удалось войти', 'Попробуйте ещё раз'); 
 

 
      } 
 
     ); 
 

 
    } 
 

 

 
    private closeWindow(): void { 
 

 
     remote.getCurrentWindow().close(); 
 

 
    } 
 

 

 
    private showLoadingAnimation(): void { 
 

 
     this.showLoading = true; 
 
     this.showLoginForm = false; 
 
     console.warn(this); 
 

 
    } 
 

 

 
    private hideLoadingAnimation(): void { 
 

 
     this.showLoading = false; 
 
     this.showLoginForm = true; 
 
     console.warn(this); 
 

 
    } 
 

 

 
}

Mais si je change la méthode de service juste pour l'expérience juste comme illustré ci-dessous (sans abonnement aux résultats d'interrogation) point de vue de composant est bien nouveau rendu.

checkAccessRights(): Observable<boolean> { 
 

 
     return new Observable((observer: Observer<boolean>) => { 
 

 
      const AUTHENTICATED = true; 
 
      const NOT_AUTHENTICATED = false; 
 

 
      this.currentUser.username = 'ADMIN'; 
 
      this.currentUser.role = 'admin'; 
 
      this.sessionService.getAccessToUser(); 
 
      observer.next(AUTHENTICATED); 
 
      observer.complete(); 
 

 
     }); 
 

 
    }
Je veux noter, que tout fonctionne si je l'utilise Promise au lieu d'observateur.

en service

checkAccessRights(): Promise<boolean> { 
 

 
     return new Promise((resolve, reject) => { 
 

 
      const queryParams: DbSelectQueryParams = { 
 
       fields: [ 
 
        `NAME`, 
 
        `ROLE` 
 
       ], 
 
       tables: [ 
 
        `SINS.P_USER` 
 
       ], 
 
       conditions: [ 
 
        `UPPER(P_USER.NAME) = UPPER(:username)`, 
 
        `AND`, 
 
        `PSWD = :password`, 
 
        `AND`, 
 
        `HASH = :hash`, 
 
        `AND`, 
 
        `LOCKED <> '1'`, 
 
        `AND`, 
 
        `ROWNUM = 1` 
 
       ] 
 
      }; 
 

 
      const bindParams = { 
 
       username: this.currentAuthData.username, 
 
       password: this.currentAuthData.password, 
 
       hash: md5(this.currentAuthData.password) 
 
      }; 
 

 
      let userIsAuthenticated = false; 
 
      const AUTHENTICATED = true; 
 
      const NOT_AUTHENTICATED = false; 
 

 
      this.dbSelect.select<CurrentUserDbRow>(queryParams, bindParams).subscribe(
 
       user => { 
 

 
        console.warn(user); 
 
        this.currentUser.username = user.NAME.toUpperCase(); 
 
        this.currentUser.role = user.ROLE.toLowerCase(); 
 

 
        this.sessionService.getAccessToUser(); 
 

 
        userIsAuthenticated = true; 
 

 
        resolve(AUTHENTICATED); 
 

 
       }, 
 
       err => { 
 

 
        reject(err); 
 
        this.logger.writeError(err); 
 

 
       }, 
 
       () => { 
 

 
        resolve(NOT_AUTHENTICATED); 
 

 
        if (userIsAuthenticated === NOT_AUTHENTICATED) { 
 
         this.logger.writeNewError('logon denied'); 
 
        } 
 

 
       } 
 
      ); 
 

 
     }); 
 

 
    }

dans le composant

this.loginService.checkAccessRights().then(
 
      accessAllowed => { 
 

 
       if (accessAllowed) { 
 

 
        this.toastService.showAdviceToast('Добро пожаловать!'); 
 

 
       } else { 
 

 
        this.hideLoadingAnimation(); 
 
        this.toastService.showErrorToastWithAdvice('ВХОД ЗАПРЕЩЁН', 'Обратитесь к администратору'); 
 

 
       } 
 

 
      } 
 
     ).catch(
 
      err => { 
 

 
       this.hideLoadingAnimation(); 
 
       this.toastService.showErrorToastWithAdvice('Не удалось войти', 'Попробуйте ещё раз'); 
 

 
      } 
 
     );

Aidez-moi, s'il vous plaît, à résoudre ce problème et à rendre le réassemblage des composants comme prévu.

+0

Parfois, le problème vient de la méthode de désabonnement. – Wandrille

+0

Dans la version précédente de ce code, la méthode de désinscription était absent, et le problème était le même –

Répondre

0

Essayez de changer quelques petites choses:

  • annoter vos champs composants comme entrées correctes - il suffit de les préfixer avec @Input;
  • Rendre ces champs publics, soit en les spécifiant explicitement ou simplement en supprimant le mot clé private.

@Input() showLoading = false; 
    @Input() showLoginForm = true; 
+0

Cela n'a également pas résolu le problème. Je veux noter que tout fonctionne si j'utilise Promise au lieu d'Observer. –