Angular 2 - 观察 firebase 数据库的结果
Angular 2 - Observe result of firebase database
我是 angular 的新人,请多关照 :)
Angular 2 ( 1.0.4 )
Angular 客户端
节点 7.9
我已经尝试创建一个集中式服务来检查用户是否已登录,如果是则检索并发回用户数据...我只尝试了 2 天,但没有成功...任何帮助将不胜感激:
import { Injectable } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabaseModule, AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Rx';
import { TipoUtente } from './tipidati' ;
import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router';
import * as firebase from 'firebase';
import 'rxjs/add/operator/toPromise' ;
@Injectable()
export class StatoutenteService implements OnInit {
constructor(private db: AngularFireDatabase, private afAuth: AngularFireAuth, private router: Router) {}
public getUserData() : Observable<any> {
this.afAuth.authState.map( auth => {
if (auth == null) {
this.Logged = false ;
this.Utente = new TipoUtente() ;
this.UId = '' ;
return undefined ;
} else {
this.Logged = true ;
this.UId = auth.uid ;
return this.dbUserData().then(data => {
console.log('leggo promessa') ;
console.log(data) ;
if (data.Livello != undefined) this.Utente = data ; else this.Utente = undefined ;
console.log(this.Utente) ;
if ( this.Utente == undefined ) { this.createNewUser() }
} ) ;
}
} ) ;
} ;
private dbUserData() : Promise<TipoUtente> {
// Controllo Utente
console.log('Recupero dati utente!') ;
console.log('UID :' + this.UId ) ;
console.log(this.Logged) ;
let utenteX = this.db.object('users/' + this.UId)
return new Promise((resolve, reject) => {
// must import 'rxjs/add/operator/first'; before using it here
utenteX.subscribe( data => {
if ( data.$value == null ) resolve(undefined); else resolve(data) ;
}, reject);
});
}
主要问题是您的 getUserData() 没有 returning 任何东西。您需要 return ovservable。
return this.afAuth.authState.map( auth => { ....
那么您应该能够像这样通过订阅 getUserData() 来访问用户数据:
this.statoutenteService.getUserData().subscribe(promisedUserData => {...})
但实际上混合 promises 和 observables 并不是一个好习惯。尝试像这样重构它:
export class StatoutenteService implements OnInit {
Logged: boolean;
UId: string;
Utente: TipoUtente;
constructor(private db: AngularFireDatabase, private afAuth: AngularFireAuth, private router: Router) {
this.Logged = false;
this.UId = '';
this.Utente = new TipoUtente();
}
public getUserData() : Observable<any> {
return this.afAuth.authState
.filter(auth => !!auth) //filters out events where auth is not truthy
.flatMap( auth => { //flatMap will resolve the returned observable (chaining observables)
this.Logged = true;
this.UId = auth.uid;
return this.db.object('users/' + this.UId);
}).map(data => {
if (data.Livello != undefined)
this.Utente = data;
else
this.Utente = undefined;
console.log(this.Utente) ;
if (this.Utente == undefined)
return this.createNewUser();
return null;
});
}
}
那么你就没有 promise 的开销了。当您随后订阅 getUserData() 可观察对象时,您将获得最后一个映射函数 returns。所以现在你会得到 this.createNewUser() 的 return 值;如果 this.Utente 之前未定义。否则为空。
您可以通过订阅它以相同的方式访问它:
this.statoutenteService.getUserData().subscribe(user => {...})
希望对你有所帮助。
您好,感谢您的回答 :) 我只是为 make 对我进行了一些编辑,现在结果好多了。然后是我之前的代码(谢谢!!)
我现在只需要监听器在未授权时接收回一个 "empty" 用户...我尝试编辑您的代码,但我得到了一个例外。
所以我尝试制作这个架构:
- 菜单栏调用服务请求用户数据
- 如果用户已登录:菜单栏根据级别获取用户数据和更新按钮
- 如果用户未登录:菜单栏显示 "Login" 按钮并隐藏菜单。
这是到目前为止编辑过的代码:
服务:
public getUserData() : Observable<any> {
return this.afAuth.authState
.flatMap( auth => { //flatMap will resolve the returned observable (chaining observables)
if ( auth == null ) {
this.Logged = false;
return undefined ; // <<< Angular doesn't like this because it expect a stream
} else {
this.Logged = true;
this.UId = auth.uid;
return this.db.object('users/' + this.UId);
}
}).map(data => {
console.log('sono dentro data') ;
console.log(data) ;
if (data.Livello != undefined) {
console.log('sono dentro if') ;
this.Utente = data;
} else {
this.Utente = undefined; }
console.log(this.Utente) ;
if (this.Utente == undefined) return this.createNewUser(); else return data ;
});
}
private createNewUser() : Observable<any> {
// Creo utente
console.log('Creo Utente!') ;
console.log(this.Logged) ;
// se non sono loggato ritorno Livello 0
if ( !this.Logged ) { return undefined } ;
// carico dati in Utente :
this.afAuth.authState.subscribe(auth => {
if (auth != undefined) {
console.log('sono in MAP') ;
this.Utente = new TipoUtente() ;
this.Utente.Cognome = auth.displayName.split(" ")[0] ;
this.Utente.Nome = auth.displayName.split(" ")[1] ;
this.Utente.DisplayName = auth.displayName ;
this.Utente.Immagine = auth.photoURL ;
this.Utente.Livello = 1 ;
this.UId = auth.uid ;
// scrivo utente :
console.log('chiamo DB') ;
return this.db.database.ref('users/' + auth.uid).set(this.Utente) ;
}
}) ;
菜单栏:
this.StatoUtente.getUserData().subscribe(data => {
this.Utente = data ;
console.log(data) ;
if ( data != undefined ) {
this.btntext = "Accedi" ;
this.LevelMenu = 0 ;
this.router.navigateByUrl('/') ;
} else {
this.btntext = "Logout" ;
this.Utente = data ;
this.LevelMenu = this.Utente.Livello ;
}
})
我是 angular 的新人,请多关照 :)
Angular 2 ( 1.0.4 ) Angular 客户端 节点 7.9
我已经尝试创建一个集中式服务来检查用户是否已登录,如果是则检索并发回用户数据...我只尝试了 2 天,但没有成功...任何帮助将不胜感激:
import { Injectable } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabaseModule, AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Rx';
import { TipoUtente } from './tipidati' ;
import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router';
import * as firebase from 'firebase';
import 'rxjs/add/operator/toPromise' ;
@Injectable()
export class StatoutenteService implements OnInit {
constructor(private db: AngularFireDatabase, private afAuth: AngularFireAuth, private router: Router) {}
public getUserData() : Observable<any> {
this.afAuth.authState.map( auth => {
if (auth == null) {
this.Logged = false ;
this.Utente = new TipoUtente() ;
this.UId = '' ;
return undefined ;
} else {
this.Logged = true ;
this.UId = auth.uid ;
return this.dbUserData().then(data => {
console.log('leggo promessa') ;
console.log(data) ;
if (data.Livello != undefined) this.Utente = data ; else this.Utente = undefined ;
console.log(this.Utente) ;
if ( this.Utente == undefined ) { this.createNewUser() }
} ) ;
}
} ) ;
} ;
private dbUserData() : Promise<TipoUtente> {
// Controllo Utente
console.log('Recupero dati utente!') ;
console.log('UID :' + this.UId ) ;
console.log(this.Logged) ;
let utenteX = this.db.object('users/' + this.UId)
return new Promise((resolve, reject) => {
// must import 'rxjs/add/operator/first'; before using it here
utenteX.subscribe( data => {
if ( data.$value == null ) resolve(undefined); else resolve(data) ;
}, reject);
});
}
主要问题是您的 getUserData() 没有 returning 任何东西。您需要 return ovservable。
return this.afAuth.authState.map( auth => { ....
那么您应该能够像这样通过订阅 getUserData() 来访问用户数据:
this.statoutenteService.getUserData().subscribe(promisedUserData => {...})
但实际上混合 promises 和 observables 并不是一个好习惯。尝试像这样重构它:
export class StatoutenteService implements OnInit {
Logged: boolean;
UId: string;
Utente: TipoUtente;
constructor(private db: AngularFireDatabase, private afAuth: AngularFireAuth, private router: Router) {
this.Logged = false;
this.UId = '';
this.Utente = new TipoUtente();
}
public getUserData() : Observable<any> {
return this.afAuth.authState
.filter(auth => !!auth) //filters out events where auth is not truthy
.flatMap( auth => { //flatMap will resolve the returned observable (chaining observables)
this.Logged = true;
this.UId = auth.uid;
return this.db.object('users/' + this.UId);
}).map(data => {
if (data.Livello != undefined)
this.Utente = data;
else
this.Utente = undefined;
console.log(this.Utente) ;
if (this.Utente == undefined)
return this.createNewUser();
return null;
});
}
}
那么你就没有 promise 的开销了。当您随后订阅 getUserData() 可观察对象时,您将获得最后一个映射函数 returns。所以现在你会得到 this.createNewUser() 的 return 值;如果 this.Utente 之前未定义。否则为空。
您可以通过订阅它以相同的方式访问它:
this.statoutenteService.getUserData().subscribe(user => {...})
希望对你有所帮助。
您好,感谢您的回答 :) 我只是为 make 对我进行了一些编辑,现在结果好多了。然后是我之前的代码(谢谢!!)
我现在只需要监听器在未授权时接收回一个 "empty" 用户...我尝试编辑您的代码,但我得到了一个例外。
所以我尝试制作这个架构:
- 菜单栏调用服务请求用户数据
- 如果用户已登录:菜单栏根据级别获取用户数据和更新按钮
- 如果用户未登录:菜单栏显示 "Login" 按钮并隐藏菜单。
这是到目前为止编辑过的代码:
服务:
public getUserData() : Observable<any> {
return this.afAuth.authState
.flatMap( auth => { //flatMap will resolve the returned observable (chaining observables)
if ( auth == null ) {
this.Logged = false;
return undefined ; // <<< Angular doesn't like this because it expect a stream
} else {
this.Logged = true;
this.UId = auth.uid;
return this.db.object('users/' + this.UId);
}
}).map(data => {
console.log('sono dentro data') ;
console.log(data) ;
if (data.Livello != undefined) {
console.log('sono dentro if') ;
this.Utente = data;
} else {
this.Utente = undefined; }
console.log(this.Utente) ;
if (this.Utente == undefined) return this.createNewUser(); else return data ;
});
}
private createNewUser() : Observable<any> {
// Creo utente
console.log('Creo Utente!') ;
console.log(this.Logged) ;
// se non sono loggato ritorno Livello 0
if ( !this.Logged ) { return undefined } ;
// carico dati in Utente :
this.afAuth.authState.subscribe(auth => {
if (auth != undefined) {
console.log('sono in MAP') ;
this.Utente = new TipoUtente() ;
this.Utente.Cognome = auth.displayName.split(" ")[0] ;
this.Utente.Nome = auth.displayName.split(" ")[1] ;
this.Utente.DisplayName = auth.displayName ;
this.Utente.Immagine = auth.photoURL ;
this.Utente.Livello = 1 ;
this.UId = auth.uid ;
// scrivo utente :
console.log('chiamo DB') ;
return this.db.database.ref('users/' + auth.uid).set(this.Utente) ;
}
}) ;
菜单栏:
this.StatoUtente.getUserData().subscribe(data => {
this.Utente = data ;
console.log(data) ;
if ( data != undefined ) {
this.btntext = "Accedi" ;
this.LevelMenu = 0 ;
this.router.navigateByUrl('/') ;
} else {
this.btntext = "Logout" ;
this.Utente = data ;
this.LevelMenu = this.Utente.Livello ;
}
})