【问题标题】:Angular2 set variable on subscribe not working订阅时的Angular2设置变量不起作用
【发布时间】:2016-09-09 15:31:28
【问题描述】:

我对 angular2 很陌生,但我尝试编写一个登录组件。一切正常,除了成功登录后我想在我的会话服务中设置用户名和密码(我存储用户名和密码以创建基本的身份验证标头)。可悲的是this._session.loggedIn 永远不会被设置。有人知道为什么吗?

export class LoginComponent {

    public email = '';
    public password = '';

    constructor(
        private _router: Router,
        private _auth: AuthenticationService,
        private _session: SessionService) {
    }

    login() {
        this._auth.login(this.email, this.password)
            .subscribe(
                data => {
                    this._session.currentProfile = data;
                    this._session.loggedIn = true;
                    this._router.navigate(['Home']);
                },
                err => {}
            );
    }
}

身份验证服务:

login(email, password){
        return this._http.get('/profile')
            .map(res => res.json());
}

【问题讨论】:

  • 什么是 login() 方法?什么时候应该调用它?如果您订阅,它不会动态调度事件。
  • @KamilMyśliwiec 我添加了登录方法。只是一个简单的http get。它在按钮按下时被调用。唯一的问题是,在订阅回调中,数据没有在会话服务中设置

标签: angular


【解决方案1】:

这段代码是传递给subscribe的函数

        data => {
            this._session.currentProfile = data;
            this._session.loggedIn = true;
            this._router.navigate(['Home']);
        }

此代码不会立即执行,但有时会在稍后执行,当来自服务器的响应到达或任何可观察对象发出新事件所需的事件时,会导致调用上述函数。

这意味着

login() {
    this._auth.login(this.email, this.password)
        .subscribe(
            data => {
                this._session.currentProfile = data;
                this._session.loggedIn = true;
                this._router.navigate(['Home']);
            },
            err => {}
        );
    // <<== at this point above code hasn't been executed yet and no values are set
}

如果您需要在数据到达时执行代码,则需要将其移动到回调中。

如果login 的调用者需要访问接收到的数据,它也必须等待数据到达。您可以通过返回 observable 来实现这一点

login() {
    return this._auth.login(this.email, this.password)
        .map(
            data => {
                this._session.currentProfile = data;
                this._session.loggedIn = true;
                this._router.navigate(['Home']);
            }
        );
}

在这种情况下,您不能使用 subscribe,因为它会返回 Subscription。如果您改用map,则会返回一个Observable,调用者可以使用它,例如

this.login().subscribe(data => this.doSomething());

这样当doSomething()被调用时,_session.currentProfile_session.loggedIn被设置并且router.navigate()被调用。

始终需要正确链接异步执行,并且无法从异步调用返回到同步执行。

【讨论】:

  • 好清楚。也许这是一个不同的问题。当我在设置后立即记录this._session.loggedIn 的值时,它是正确的,但随后我导航到一个新组件Home,在其中我再次注入SessionServicethis._session.loggedIn 的值不正确。我认为在 angular2 中所有服务都是单例的?
  • 您似乎没有将值存储在服务中。仅在调用login() 的组件中。 Angular2 中的服务是每个提供者的单例。如果您在组件上提供它,您将获得每个组件实例的服务实例。如果你在延迟加载模块中提供它,你会得到另一个实例,因为延迟加载模块的提供者没有收集在根提供者中(它们有自己的根范围。添加到其他 @NgModules() 的提供者被收集在应用程序根范围中只会是一个实例。
  • 我认为这就是问题所在。所以我只需要在app.module.ts 中使用@NgModules() 注册服务,它应该可以工作吗?
  • 要么添加它,要么将其添加到 providers: [AuthenticationService] 或其他一些 @NgModule(),然后添加到 imports: [] 中的 app.module.ts
猜你喜欢
  • 1970-01-01
  • 2016-09-26
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-07
  • 2014-11-13
  • 2016-10-15
相关资源
最近更新 更多