Питання, з якими я стикався з порожнімполя значень мали відношення до неіснуючих ключів у моїй базі даних, тому більшість дискурсів тут не стосується вашого питання. Якщо ви шукаєте спосіб "приєднатись" до запитів у AngularFire2, прийнята відповідь нижче робить прекрасна робота цього. Зараз я використовую combineLatest
замість forkJoin
. Для цього ви повинні import "rxjs/add/observable/combineLatest";
.
У мене є така денормалізована структура Firebase:
members
-memberid1
-threads
-threadid1: true,
-threadid3: true
-username: "Adam"
...
threads
-threadid1
-author: memberid3
-quality: 67
-participants
-memberid2: true,
-memberid3: true
...
Я хочу винести username
в моєму threads
вид, який сортується за quality
.
Моя послуга:
getUsername(memberKey: string) {
return this.af.database.object("/members/" + memberKey + "/username")
}
getFeaturedThreads(): FirebaseListObservable<any[]> {
return this.af.database.list("/threads", {
query: {
orderByChild: "quality",
endAt: 10
}
});
}
Мій компонент:
ngOnInit() {
this.threads = this.featuredThreadsService.getFeaturedThreads()
this.threads.subscribe(
allThreads =>
allThreads.forEach(thisThread => {
thisThread.username = this.featuredThreadsService.getUsername(thisThread.author)
console.log(thisThread.username)
})
)
}
Чомусь це записує те, що схоже на невиконані спостереження на консолі.
Я хотів би отримати ці значення у властивості threads
тож я можу надати це на мій погляд так:
<div *ngFor="let thread of threads | async" class="thread-tile">
...
{{threads.username}}
...
</div>
Оновлено: console.log
за allThreads
і thisThread
Оновлено: підписався на getUsername ()
this.featuredThreadsService.getUsername(thisThread.author)
.subscribe( username => console.log(username))
Результатом цього є об'єкти без значень:
Відповіді:
4 для відповіді № 1Ви можете скласти спостережуване на основі getFeaturedThreads
який запитує членів і замінює значення в кожному потоці "s participants
власність з іменами користувачів:
import { Observable } from "rxjs/Observable";
import "rxjs/add/observable/forkJoin";
import "rxjs/add/operator/do";
import "rxjs/add/operator/first";
import "rxjs/add/operator/switchMap";
let featuredThreadsWithUserNames = this.getFeaturedThreads()
// Each time the getFeaturedThreads emits, switch to unsubscribe/ignore
// any pending member queries:
.switchMap(threads => {
// Map the threads to the array of observables that are to be
// joined. When the observables emit a value, update the thread.
let memberObservables = [];
threads.forEach(thread => {
// Add the author:
memberObservables.push(this.af.database
.object(`members/${thread.author}`)
.first()
.do(value => { thread.author = value.username; })
);
// Add the participants:
Object.keys(thread.participants).forEach(key => {
memberObservables.push(this.af.database
.object(`members/${key}`)
.first()
.do(value => { thread.participants[key] = value.username; })
);
});
});
// Join the member observables and use the result selector to
// return the threads - which will have been updated.
return Observable.forkJoin(...memberObservables, () => threads);
});
Це дасть вам спостереження, яке випромінюється кожного разу getFeaturedThreads
випускає. Однак, якщо імена користувачів змінюються, це не призведе до повторної передачі. Якщо це важливо, замініть forkJoin
з combineLatest
і видаліть first
Оператор із складеного члена спостерігає.
0 для відповіді № 2
Щоб вирішити приєднання до користувачів, я написав сервіс, який кешує користувачів, які вже отримані, і відображає їх у референтні дані з мінімальним кодом. Для з'єднання використовується вкладена структура карти:
constructor(public db: AngularFireDatabase, public users:UserProvider) {
this.threads = db.list("threads").valueChanges().map(messages => {
return threads.map((t:Message) => {
t.user = users.load(t.userid);
return m;
});
});
}
А служба UserProvider виглядає так:
@Injectable()
export class UserProvider {
db: AngularFireDatabase;
users: Map<String, Observable<User>>;
constructor(db: AngularFireDatabase) {
this.db = db;
this.users = new Map();
}
load(userid:string) : Observable<User> {
if( !this.users.has(userid) ) {
this.users.set(userid, this.db.object(`members/${userid}`).valueChanges());
}
return this.users.get(userid);
}
}
Там є повний робочий приклад з'єднувальних пристроїв і всіх котлоагрегатів тут