服务中的错误上下文绑定

Bad context binding within service

我正在尝试在 AuthenticationService 上设置 token 属性。

这是我的代码:

authentication.service.ts

import { Injectable } from '@angular/core'
import { Http, Headers, Response } from '@angular/http'
import { Observable, BehaviorSubject } from 'rxjs'
import 'rxjs/add/operator/map'
import { Login } from '../../+authentication/shared/models'
import { config } from '../config'

@Injectable()
export class AuthenticationService {
  private token: string
  private _isConnected = new BehaviorSubject<boolean>(false)
  isConnected$ = this._isConnected.asObservable()

  constructor (private http: Http) {
    const currentToken = JSON.parse(localStorage.getItem('currentToken'))
    if (currentToken) {
      this.token = currentToken.token 
      this._isConnected.next(true) // work
    }
  }

  login (login: Login): Observable<any> {
    return this.http.post(config.BASE_URL + '/auth/login', login)
      .map((response: Response) => {
        if (response.json() && response.json().success) {
          const token = response.json() && response.json().token
          this.token = token// don't do the work
          this._isConnected.next(true) // don't do the work neither

          localStorage.setItem('currentToken', JSON.stringify({token}))

          return {
            success: true
          }
        } else if (response.json() && response.json().message) {
          return {
            success: false,
            message: response.json().message
          }
        }
      })
  }

  logout (): void {
    this.token = null
    this._isConnected.next(false) // work
    localStorage.removeItem('currentToken') // work
  }

  logToken (): void {
    console.log(this.token) // null
    console.log(localStorage.getItem('currentToken')) // {"token":"eyJhb..."}

    // do the work
    this.token = localStorage.getItem('currentToken')
    console.log(this.token)

    // do the work too
    this._isConnected.next(true)
  }
}

来自 login.component.ts

import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router'

import { AuthenticationService } from '../../shared/services'

import { Login } from '../shared/models/index'

@Component({
  selector: 'login',
  templateUrl: './login.component.html',
})
export class LoginComponent {
  public login: Login = new Login('test@test.fr', 'test')
  public authError: string

  constructor (
    private router: Router,
    private as: AuthenticationService
  ) {
    if (as.getToken()) {
      this.router.navigate(['/home']) // This work !! That's not 
    }
  }

  onSubmit () {
    this.as.login(this.login)
      .subscribe((result) => {
        if (result.success) {
          this.router.navigate(['/home']) // working
        } else if (result.message) {
          this.authError = result.message // working
        }
      })
  }
}

authentication.service.ts的最后可以看到logToken函数:

logToken (): void {
    console.log(this.token) // null
    console.log(localStorage.getItem('currentToken')) // {"token":"eyJhb..."}

    // do the work
    this.token = localStorage.getItem('currentToken')
    console.log(this.token)

    // do the work too
    this._isConnected.next(true)
  }

我通过单击导航栏中的按钮从我的应用程序组件手动调用它,并且从未设置令牌 属性,除非我重新加载页面,在这种情况下,它由服务的构造函数设置,谁从 LocalStorage 获取它。

请告诉我为什么 let 不想工作,我使用箭头函数绑定它但它似乎不起作用。

提前致谢

SherlockStd

编辑

我尝试将响应处理委托给私有方法来查看 this 绑定是否更好,但它仍然无法正常工作(authentication.service.ts):

  login (login: Login): Observable<any> {
    return this.http.post(config.BASE_URL + '/auth/login', login)
      .map((response: Response) => this.handleResponse(response))
  }

  private handleResponse (response: Response) {
    if (response.json() && response.json().success) {
          // login successful if there's a jwt token in the response
      const token = response.json() && response.json().token
      this.token = token

      localStorage.setItem('currentToken', JSON.stringify({token}))

      return {
        success: true
      }
    } else if (response.json() && response.json().message) {
      return {
        success: false,
        message: response.json().message
      }
    }
  }

编辑 2

我在 login()logToken() 函数中记录了 authentication.service.ts 中的 this 关键字。 它每次 return 一个 AuthenticationService,包含相同的属性,但在登录函数中它包含 token 属性,该属性在此函数之外丢失。

经过3天的研究,我终于找到了这个问题的根源。

我在父 (app.module.ts) 和子 (authentication.module.ts) 模块中声明了相同的服务(参见下面的结构)。

src/
├── app.component.html
├── app.component.ts
├── app.module.ts <== provide AuthenticationService
├── app.routes.ts <== load authentication.module with router.loadChildren()
│
├── +authentication/
│   ├── authentication.component.html
│   ├── authentication.component.ts
│   ├── authentication.module.ts <== provide AuthenticationService
│   ├── authentication.routes.ts <== expose a route to login component
│   └── login
│       ├── login.component.html
│       └── login.component.ts <== using service's methods here don't work
│
└── shared/
    └── services/
        ├── authentication.service.ts
        └── base.service.ts

我不明白为什么它会影响 this 绑定,但它现在可以工作了,我打开了一个 issue on Github 因为我认为在这种情况下应该会出现错误。

感谢您的帮助。