如何使用服务存储Angular2的全局变量

How to store global variable of Angular2 with Service

我使用 AuthService 连接到我的授权服务器并存储授权状态,这是必要的代码:

auth.service.ts

@Injectable()
export class AuthService {

  state = {
    isLoggedIn: false,
    redirectUrl: ''
  };


  private authUrl = 'http://localhost:3000/admin/auth'; 

  constructor(private http:Http) {

    this.state.isLoggedIn = false;
    this.state.redirectUrl = '';
  }

  auth(name:string, password:string):Observable<Auth> {

    let headers = new Headers({'Content-Type': 'application/json'});
    let options = new RequestOptions({headers: headers});

    return this.http.post(this.authUrl, {name: name, pw: password}, options)
      .map(this.extractData, this.state)
      .catch(this.handleError);
  }

  extractData(res:Response) { // <-- this.state become undefined

    let body = res.json();

    this.state.isLoggedIn = (body.res == 0); // <-- Cannot read property 'isLoggedIn' of undefined

    return body || {};
  }
}

auth-guard.service.ts

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private authService:AuthService, private router:Router) {
  }

  canActivate(route:ActivatedRouteSnapshot, stateSnapshot:RouterStateSnapshot):boolean {

    // this.authService.state.isLoggedIn: false
    // this.authService.state.redirectUrl: ''

    let url:string = stateSnapshot.url;

    return this.checkLogin(url);
  }

  checkLogin(url:string):boolean {

    // this.authService.state.isLoggedIn: false

    if (this.authService.state.isLoggedIn) {
      return true;
    }

    // Store the attempted URL for redirecting
    this.authService.state.redirectUrl = url;

    // this.authService.state.redirectUrl: '/admin'

    // Navigate to the login page with extras
    this.router.navigate(['/admin/auth']);
    return false;
  }
}

当我尝试使用名称和密码登录时,auth.service.ts 显示:Cannot read property 'isLoggedIn' of undefined.

我不知道为什么以及什么时候 state 变得未定义。

看来您的问题源于这行代码

return this.http.post(this.authUrl, {name: name, pw: password}, options)
  .map(this.extractData, this.state) //<-- right here
  .catch(this.handleError);

地图状态的 RXJS 文档:

map(project: function(value: T, index: number): R, thisArg: any): Observable Applies a given project function to each value emitted by the source Observable, and emits the resulting values as an Observable.

具体看一下map中第二个参数的定义。这指定了 "this" 指针。

由于您已将其设置为 this.state,并且状态没有 属性 称为状态,因此您未定义。

您可以传递一个不会尝试重新绑定 this 指针的 lambda

return this.http.post(this.authUrl, {name: name, pw: password}, options)
  .map((res) => this.extractData(res)) <-- lambda instead
  .catch(this.handleError);

或者你可以明确地传递正确的 this 指针作为第二个参数

return this.http.post(this.authUrl, {name: name, pw: password}, options)
  .map(this.extractData, this)
  .catch(this.handleError);

尝试

this.extractData.bind(this);

*不适用于 with => 函数。

当调用 extractData 时,上下文发生了变化。使用 fat arrow 来避免这种情况。

     return this.http.post(this.authUrl, {name: name, pw: password}, options)
      .map((res) => this.extractData(res))
      .catch(this.handleError);