Angular2 - 无法读取嵌套调用中未定义的 属性 'subscribe'
Angular2 - Cannot read property 'subscribe' of undefined in nested call
我查看了包括 , and this 在内的许多资源,但未能获得预期的结果。
我要做的就是对用户进行身份验证(使用 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
我可以看到各个方法都按预期工作。用户进行身份验证,并加载配置文件(显示在日志中)。由于我不知道的原因,问题在于订阅事件。
我认为问题在于 getProfile
并不是真正的 return 和 Observable
。
您使用 flatMap
以便您可以将可观察序列和 return 配置文件链接为可观察对象。但是为了让它工作,你在 flatMap
中的回调应该 return 一个承诺或一个可观察的(正如我从 this answer 中学到的)。否则可观察链被打破。
所以你可能需要做的是:
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,它似乎已经解决了这个问题。
这是代码的样子,它通过 promise 正确验证,然后成功加载配置文件,然后加载下一页:
我的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)
});
}
The callstack:
- User is authenticated
- Subscribe to getProfile and wait for method to finish...
- GetProfile() method executes
- Profile is set
- Page is redirected
我查看了包括
我要做的就是对用户进行身份验证(使用 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
我可以看到各个方法都按预期工作。用户进行身份验证,并加载配置文件(显示在日志中)。由于我不知道的原因,问题在于订阅事件。
我认为问题在于 getProfile
并不是真正的 return 和 Observable
。
您使用 flatMap
以便您可以将可观察序列和 return 配置文件链接为可观察对象。但是为了让它工作,你在 flatMap
中的回调应该 return 一个承诺或一个可观察的(正如我从 this answer 中学到的)。否则可观察链被打破。
所以你可能需要做的是:
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,它似乎已经解决了这个问题。
这是代码的样子,它通过 promise 正确验证,然后成功加载配置文件,然后加载下一页:
我的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)
});
}
The callstack:
- User is authenticated
- Subscribe to getProfile and wait for method to finish...
- GetProfile() method executes
- Profile is set
- Page is redirected