我正在用Gooogle OAuth制作一个youtube播放列表项目,我在处理身份验证过程时遇到了一个小问题,变量isAuthorized是我存储用户登录状态的地方,我可以在控制台中看到,用户登录后它变为true,但在视图部分它仍然是false.我想知道我到底是怎么解决这个问题的?

下面是我在模型部分的代码

GoogleAuth: any;
user: any;
isAuthorized = false;

 ngOnInit(): void {
    // Load auth2 library
    gapi.load("client:auth2", this.initClient);
  }

  loadClient = () => {
    gapi.client.setApiKey(this.API_KEY);
    return gapi.client
      // same as "https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest"
      .load("youtube", "v3")
      .then(
        () => {
          console.log("GAPI client loaded for API");
        },
        function (err) {
          console.error("Error loading GAPI client for API", err);
        }
      );
  }

  // Init API client library and set up sign in listeners
  initClient = () => {
    gapi.client
      .init({
        discoveryDocs: this.DISCOVERY_DOCS,
        clientId: this.CLIENT_ID,
        scope: this.SCOPES,
      })
      .then(() => {
        this.GoogleAuth = gapi.auth2.getAuthInstance();
        // Listen for sign-in state changes.
        this.GoogleAuth.isSignedIn.listen(this.handleSigninStatus);

        // Handle initial sign-in state. (Determine if user is already signed in.)
        this.handleSigninStatus();
        this.loadClient()
      });
  }

  handleSigninStatus = () => {
    this.user = this.GoogleAuth.currentUser.get();
    this.isAuthorized = this.user.hasGrantedScopes(this.SCOPES);
    if (this.isAuthorized) {
      this.loadClient()
      // this.getChannelInfo() //display playlist data
    } else {
      //do nothing
    }
  }

  // Handle login
  handleAuthClick = () => {
    this.GoogleAuth.signIn({ scope: this.SCOPES })
      .then(() => {
        console.log("Sign-in successful");
        // this.isLoggedIn = true
        this.getChannelInfo()
      },
        (err: any) => { console.error("Error signing in", { err }) });
  }

  // Handle logout
  handleSignoutClick = () => {
    this.GoogleAuth.signOut();
    this.GoogleAuth.disconnect();
    // gapi.auth2.getAuthInstance().signOut().then(() => { this.googleUser = null });
  }

这是我的HTML,也就是视图部分:

<mat-toolbar>
      <a href="/">My Application {{isAuthorized}}</a>
      <ng-template [ngIf]="isAuthorized" [ngIfElse]="loggedOut">
        <button mat-raised-button color="warn" id="signout-button" (click)="handleSignoutClick()">Log Out</button>
      </ng-template>
      <ng-template #loggedOut>
        <button mat-raised-button color="warn" id="authorize-button" (click)="handleAuthClick()">Log In</button>
      </ng-template>
    </mat-toolbar>

enter image description here

推荐答案

因为this.GoogleAuth个事件在angular的作用域/区域之外运行,所以需要将其回调带到angular区域.这样,angular的生命周期事件将适当地处理数据上的更改.

ngZone's run函数包装事件处理程序函数.建议每次通过不属于Angular 范围/区域的事件修改Angular 监控变量时:

constructor(private ngZone: NgZone ... 

...

initClient = () => {
    gapi.client
      .init({
        discoveryDocs: this.DISCOVERY_DOCS,
        clientId: this.CLIENT_ID,
        scope: this.SCOPES,
      })
      .then(() => {
  this.ngZone.run(() => { // <-- here
        this.GoogleAuth = gapi.auth2.getAuthInstance();
        // Listen for sign-in state changes.
        this.GoogleAuth.isSignedIn.listen(this.handleSigninStatus);

        // Handle initial sign-in state. (Determine if user is already signed in.)
        this.handleSigninStatus();
        this.loadClient()
  });
      });
  }


handleSigninStatus = () => {
  this.ngZone.run(() => { // <-- here
    this.user = this.GoogleAuth.currentUser.get();
    this.isAuthorized = this.user.hasGrantedScopes(this.SCOPES);
    if (this.isAuthorized) {
      this.loadClient()
      // this.getChannelInfo() //display playlist data
    } else {
      //do nothing
    }
  });
}

将模型修改引入angular的作用域/区域的最简单方法是使用如上所述的ngZone调用来包装它们.

Angular相关问答推荐

如何在每次Angular 编译之前执行脚本(esbuild)

停靠的Angular 应用程序的Nginx反向代理无法加载assets资源

首期日历发行

ANGLE DI useFactory将参数传递给工厂函数

由于ngcc操作失败,Angular扩展可能无法正常工作

在指令中获取宿主组件的templateRef

URL 更改但组件未在 Angular 导航中呈现

Angular UNIVERSAL prerender 错误方法 Promise.prototype.then 调用不兼容的接收器 [object Object]

尽管模型中的变量发生了变化,但Angular 视图没有更新

刷新页面导致 401 错误-Angular 8

我应该在 Jasmine 3 中使用什么来代替 fit 和 fdescribe?

使用 rxjs 处理刷新令牌

如何在插值中编写条件?

如何在 ngFor 循环中创建变量?

如何在angular 5 中获取基本网址?

Angular CLI 自定义 webpack 配置

Angular url加号转换为空格

Angular 2:将外部js文件导入组件

为什么 Angular 项目中没有 Angular-CLI 为 model生成命令?

Angular 2:从父组件获取 RouteParams