angular - 'ادغام' پرس و جوهای Firebase در Angularfire2
بهروزرسانی :
مسائلی که با فیلدهای مقدار خالی مواجه بودم مربوط به کلیدهای ناپیدا در پایگاه داده من بود، بنابراین بیشتر بحثها در اینجا به سؤال شما مربوط نمیشود. اگر به دنبال روشی برای «ادغام» پرسوجوها در AngularFire2 هستید، پاسخ پذیرفته شده زیر این کار را به خوبی انجام میدهد. در حال حاضر من از combineLatest به جای forkJoin استفاده میکنم. برای انجام این کار باید import 'rxjs/add/observable/combineLatest'; را انجام دهید.
من ساختار فايربیس دنورمالیزه شده زیر را دارم:
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))
نتیجهٔ این، اشیایی بدون مقادیر است:
پاسخ شماره ۱
شما میتوانید یک Observable بر اساس getFeaturedThreads بسازید که اعضا را جستجو کند و مقادیر در هر ویژگی 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);
});
این به شما یک Observable میدهد که هر بار که getFeaturedThreads منتشر میکند، پخش میشود. با این حال، اگر نامهای کاربری تغییر کنند، دوباره منتشر نخواهد شد. اگر این مهم است، forkJoin را با combineLatest جایگزین کنید و عملگر first را از Observables اعضای ترکیبی حذف کنید.
پاسخ شماره ۲
برای حل پیوستها روی کاربران، من سرویسی نوشتم که کاربران گرفتهشده را کش میکند و آنها را با حداقل کد به دادههای ارجاع شده نگاشت میکند. این از یک ساختار نقشه تو در تو برای انجام پیوست استفاده میکند:
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);
}
}
یک مثال کامل و کاربردی از جوینها و تمام کدهای پایهای اینجا وجود دارد



