Angular 9 在服务收到回调后刷新组件
Angular 9 refresh component after callback received on service
我是 Angular 的新人,也有点迷茫。我正在尝试在 angular 应用程序中实现 google 登录,但我无法使其正常工作。这个想法是显示登录按钮,一旦用户完成它,刷新显示他的数据和照片的组件。
我使用他们的方法成功初始化了gApi并订阅了登录事件,但我不知道如何让组件在调用相应的监听器后重新加载。我一直在尝试使用 subject.AsObservable() -> subscription 来尝试处理这个问题,即使我知道回调被调用,组件也不会更新。
一位朋友告诉我使用 EventEmmitter 来处理这个问题,但是由于回调在服务内部并且我不需要重新加载父项,所以我不确定这是否可行。
我也在阅读有关 ngZones 的文章,它可以解决问题(但我不确定这是否是一种反模式)。我在这里写下我现在的代码。
header.html
<div *ngIf="this.loggedIn else showLogin">
<p>{{this.getBasicProfile().getName()}}</p>
<p>{{this.getBasicProfile().getEmail()}}</p>
<img [src]="this.getBasicProfile().getImageUrl()"/>
</div>
<ng-template #showLogin>
{{this.loggedIn}}
<div class="g-signin2"></div>
</ng-template>
header.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { GoogleService } from '../google.service'
import { Subscription } from 'rxjs';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.sass']
})
export class HeaderComponent implements OnInit, OnDestroy {
constructor(protected google : GoogleService) {
}
loggedIn: boolean = false;
subscription : Subscription;
getBasicProfile() {
return this.google.getUserProfile();
}
ngOnInit(): void {
this.subscription = this.google.loggedIn$.subscribe(loggedIn => {
this.loggedIn = loggedIn;
});
this.google.init().then(() => {
this.google.listenUserChanges();
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
google.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subscriber } from 'rxjs';
declare const gapi: any;
@Injectable({
providedIn: 'root'
})
export class GoogleService {
private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
auth: any;
profile: any;
loggedIn$ = this.loggedIn.asObservable();
public init(): Promise<boolean> {
let doInit = new Promise<boolean>((resolve, reject) => {
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: "XXXXXX.apps.googleusercontent.com",
cookiepolicy: 'single_host_origin',
}).then(auth => {
this.auth = auth;
resolve();
});
});
});
return doInit;
}
public listenUserChanges(): void {
if (!this.isLoggedIn()) {
this.auth.isSignedIn.listen(() => {
this.getUserProfile()
});
this.auth.currentUser.listen(() => {
this.getUserProfile()
});
}
}
public isLoggedIn(): boolean {
if (this.auth) {
let isLoggedIn = this.auth.isSignedIn.get();
this.loggedIn.next(isLoggedIn);
return isLoggedIn;
}
return false;
}
public getUserProfile(): any {
if (this.auth && this.isLoggedIn()) {
this.profile = this.auth.currentUser.get().getBasicProfile();
return this.profile;
}
return null;
}
constructor() {
this.auth = null;
}
}
任何建议都将受到欢迎。
谢谢!!
正如@amakhrov 建议使用 ngZone.run() 我能够在使用 google API 完成登录时更新组件。另外,使用订阅模型进行重构以避免不必要的更新的想法很有趣,谢谢!
我是 Angular 的新人,也有点迷茫。我正在尝试在 angular 应用程序中实现 google 登录,但我无法使其正常工作。这个想法是显示登录按钮,一旦用户完成它,刷新显示他的数据和照片的组件。
我使用他们的方法成功初始化了gApi并订阅了登录事件,但我不知道如何让组件在调用相应的监听器后重新加载。我一直在尝试使用 subject.AsObservable() -> subscription 来尝试处理这个问题,即使我知道回调被调用,组件也不会更新。
一位朋友告诉我使用 EventEmmitter 来处理这个问题,但是由于回调在服务内部并且我不需要重新加载父项,所以我不确定这是否可行。
我也在阅读有关 ngZones 的文章,它可以解决问题(但我不确定这是否是一种反模式)。我在这里写下我现在的代码。
header.html
<div *ngIf="this.loggedIn else showLogin">
<p>{{this.getBasicProfile().getName()}}</p>
<p>{{this.getBasicProfile().getEmail()}}</p>
<img [src]="this.getBasicProfile().getImageUrl()"/>
</div>
<ng-template #showLogin>
{{this.loggedIn}}
<div class="g-signin2"></div>
</ng-template>
header.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { GoogleService } from '../google.service'
import { Subscription } from 'rxjs';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.sass']
})
export class HeaderComponent implements OnInit, OnDestroy {
constructor(protected google : GoogleService) {
}
loggedIn: boolean = false;
subscription : Subscription;
getBasicProfile() {
return this.google.getUserProfile();
}
ngOnInit(): void {
this.subscription = this.google.loggedIn$.subscribe(loggedIn => {
this.loggedIn = loggedIn;
});
this.google.init().then(() => {
this.google.listenUserChanges();
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
google.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Subscriber } from 'rxjs';
declare const gapi: any;
@Injectable({
providedIn: 'root'
})
export class GoogleService {
private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
auth: any;
profile: any;
loggedIn$ = this.loggedIn.asObservable();
public init(): Promise<boolean> {
let doInit = new Promise<boolean>((resolve, reject) => {
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: "XXXXXX.apps.googleusercontent.com",
cookiepolicy: 'single_host_origin',
}).then(auth => {
this.auth = auth;
resolve();
});
});
});
return doInit;
}
public listenUserChanges(): void {
if (!this.isLoggedIn()) {
this.auth.isSignedIn.listen(() => {
this.getUserProfile()
});
this.auth.currentUser.listen(() => {
this.getUserProfile()
});
}
}
public isLoggedIn(): boolean {
if (this.auth) {
let isLoggedIn = this.auth.isSignedIn.get();
this.loggedIn.next(isLoggedIn);
return isLoggedIn;
}
return false;
}
public getUserProfile(): any {
if (this.auth && this.isLoggedIn()) {
this.profile = this.auth.currentUser.get().getBasicProfile();
return this.profile;
}
return null;
}
constructor() {
this.auth = null;
}
}
任何建议都将受到欢迎。
谢谢!!
正如@amakhrov 建议使用 ngZone.run() 我能够在使用 google API 完成登录时更新组件。另外,使用订阅模型进行重构以避免不必要的更新的想法很有趣,谢谢!