首页 > 解决方案 > Angular 9:使用命名函数作为 then()、listen() 和 subscribe() 的参数的范围问题

问题描述

在理解为什么我遇到范围问题时遇到了一些麻烦。

使用内部定义的函数时then(),一切正常:

import GoogleAuth = gapi.auth2.GoogleAuth;
import GoogleUser = gapi.auth2.GoogleUser;

@Injectable()
export class MyService {
  constructor() { }

  private googleAuth: GoogleAuth = undefined;
  private clientConfig = { ... };

  public init(): void {
    gapi.load('auth2', () => {
      gapi.auth2.init(this.clientConfig)
        .then((response: GoogleAuth) => {
          this.googleAuth = response;
      });
    });
  }
}

但是,当我尝试使用命名函数作为 then() 的参数时,出现错误(代码行旁边):

import GoogleAuth = gapi.auth2.GoogleAuth;
import GoogleUser = gapi.auth2.GoogleUser;

@Injectable()
export class MyService {
  constructor() { }

  private googleAuth: GoogleAuth = undefined;
  private clientConfig = { ... };

  private onInit(response: GoogleAuth): void {
    console.log(this); // undefined
    this.googleAuth = response; // Cannot read property 'googleAuth' of undefined
  }

  public init(): void {
    gapi.load('auth2', () => {
      gapi.auth2.init(this.clientConfig)
        .then(this.onInit);
    });
  }
}

起初我以为是因为我将undefined分配为“googleAuth”的值,但即使我运行“console.log(this);” 在“onInit”内部,未定义是出现在控制台中的内容。如果我要手动调用该方法并传递预期的参数,则可以轻松查看“this”和“this.googleAuth”。使用 listen() 和 subscribe() 时,我遇到了完全相同的问题。

我该如何解决这个问题?

标签: angularscoping

解决方案


您将函数传递this.onInit给的方式then,您失去了上下文。正确的做法是

    public init(): void {
      gapi.load('auth2', () => {
        gapi.auth2.init(this.clientConfig)
          .then((resp) => this.onInit(resp));
        });
    }

注意使用粗箭头函数。


推荐阅读