【问题标题】:Angular2 - Cannot read property 'subscribe' of undefined in nested callAngular2 - 无法读取嵌套调用中未定义的属性“订阅”
【发布时间】:2017-05-09 05:31:27
【问题描述】:

我查看了许多资源,包括thisthisthis,但我一直无法达到预期的效果。

我要做的就是对用户进行身份验证(使用 firebase),然后在通过身份验证后,加载他们的个人资料并将其存储在变量 userProfile 中,然后再加载下一页仪表板:

我的登录服务:

public signinUser(user: User) {
    this.af.auth.login({
        email: user.email,
        password: user.password
    },
        {
            provider: AuthProviders.Password,
            method: AuthMethods.Password
        }

    )
        .then(                
        success => {
            console.log('Authenticated');
            this.getProfile().subscribe( // PROBLEM is here
                profile => {
                    console.log(profile);
                    console.log('Profile Loaded');
                    this.router.navigate(['/dashboard']);
                }
            )               
        }
        )
        .catch(function (error) {
            ...
            console.log('ERROR SIGNING USER IN');
        }

我的getProfile() 方法:

public getProfile(): Observable<any> {            
        return this.af.database.object('/profiles/' + this.user.uid)
        .flatMap(
            profile => {
                console.log('inside success');
                console.log(profile);
                this.userProfile = <User>profile;                    
                console.log('getProfile has completed');       
                return profile;
            },
            error => {
                console.log(error)
            });

这是部分日志的外观:

Authenticated
auth.service.ts:104 ERROR SIGNING USER IN
auth.service.ts:105 TypeError: Cannot read property 'subscribe' of undefined
at auth.service.ts:91
at ZoneDelegate.invoke (zone.js:232)
at Object.onInvoke (ng_zone.js:238)
at ZoneDelegate.invoke (zone.js:231)
at Zone.run (zone.js:114)
at zone.js:502
at ZoneDelegate.invokeTask (zone.js:265)
at Object.onInvokeTask (ng_zone.js:229)
at ZoneDelegate.invokeTask (zone.js:264)
at Zone.runTask (zone.js:154)
auth.service.ts:106 Cannot read property 'subscribe' of undefined
auth.service.ts:184 inside success
auth.service.ts:185 Object {confirmPassword: "123123", email: "aaa@gmail.com2", github: "aaa" name: "a", password: "123123"…}
auth.service.ts:188 
getProfile has completed()
auth.service.ts:185

我可以看到这些方法单独按预期工作。用户进行身份验证,并加载配置文件(显示在日志中)。问题在于订阅事件,原因我不知道。

【问题讨论】:

    标签: angular asynchronous callback observable chaining


    【解决方案1】:

    好吧,这很奇怪,但我重新启动了 webpack,它似乎已经解决了这个问题。

    这就是代码的外观,它通过承诺正确地进行身份验证,然后在成功时加载配置文件,然后加载下一页:

    我的signinUser 方法:

    public signinUser(user: User) {
        this.af.auth.login({
            email: user.email,
            password: user.password
        },
            {
                provider: AuthProviders.Password,
                method: AuthMethods.Password
            }
    
        )
            .then(                
            success => {
                console.log('Authenticated');
                this.getProfile().subscribe(
                    profile => {
                        this.router.navigate(['/dashboard']);
                    }, 
                    error => console.log(error)
                )
    

    还有我的getProfile 方法:

    public getProfile(): Observable<User> {        
            return this.af.database.object('/profiles/' + this.user.uid)
            .map(                
                profile => {
                    console.log('inside success');
                    console.log(profile);
                    this.userProfile = <User>profile;                    
                    console.log(this.userProfile);        
                    return profile;
                },
                error => {
                    console.log(error)
                });
    }
    

    调用栈:

    1. 用户已通过身份验证
    2. 订阅 getProfile 并等待方法完成...
      1. GetProfile() 方法执行
      2. 个人资料已设置
    3. 页面被重定向

    【讨论】:

    • “我重新启动了 webpack,它似乎已经解决了这个问题”——它对我有帮助(Angular 5)
    【解决方案2】:

    我认为问题在于getProfile 并没有真正返回Observable

    您使用flatMap,因此您可以链接可观察序列并将配置文件作为可观察对象返回。但是为了让它工作,你在flatMap 中的回调应该返回一个promise 或一个observable(正如我从this answer 学到的)。否则 observables 链会中断。

    所以你可能需要做的是:

    public getProfile(): Observable<any> {            
            return this.af.database.object('/profiles/' + this.user.uid)
            .flatMap(
                profile => {
                    console.log('inside success');
                    console.log(profile);
                    this.userProfile = <User>profile;                    
                    console.log('getProfile has completed');       
                    return Promise.resolve(profile);//<-- this is what needs to be changed
                },
                error => {
                    console.log(error)
                });
    

    【讨论】:

    • 感谢您的回答。我最终做了一些小改动并重新启动webpack,它奇怪地解决了我的问题。这也是我认为链式序列没有返回可观察值,因此出现错误。 +1 表示感谢,我认为这将是另一个有用的答案!
    猜你喜欢
    • 2016-09-17
    • 2018-01-13
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多