5

Update:

Проблемы, я сталкивался с полями пустых значений пришлось делать с несуществующими ключами в моей базе данных, поэтому большая часть речи не будет применяться к вашему вопрос. Если вы ищете способ «присоединиться» к запросам в AngularFire2, принятый ниже ответ прекрасно справляется с этим. В настоящее время я использую combineLatest вместо forkJoin. Для этого вам нужно import 'rxjs/add/observable/combineLatest';.«Объединение» Firebase запросов в Angularfire2

У меня есть следующая денормализованный 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) 
     }) 
    ) 
} 

По какой-то причине это регистрирует то, что выглядит как невыполненных наблюдаемыми на консоль.

enter image description here

Я хотел бы получить эти значения в свойстве threads, так что я могу сделать его на мой взгляд, как это:

<div *ngFor="let thread of threads | async" class="thread-tile"> 
    ... 
    {{threads.username}} 
    ... 
</div> 

Обновлено: console.log для allThreads и thisThread

enter image description here

enter image description here

Обновлено: подписка на GetUserName()

this.featuredThreadsService.getUsername(thisThread.author) 
     .subscribe(username => console.log(username)) 

Результатом этого является объекты без каких-либо значений:

enter image description here

+0

Ваших Метод getUsername не возвращает ничего. Это предназначено? – echonax

+0

Приношу свои извинения. Это остаток от другой реализации. Я изменил его. Текущий метод ведет себя так, как я описываю в своем вопросе. –

+0

Можете ли вы поставить console.log для 'allThreads' и' thisThread', чтобы убедиться, что они определены? – echonax

ответ

4

Вы можете составить наблюдаемым на основе 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); 
    }); 

Это даст вам возможность наблюдать, что каждый раз испускает getFeaturedThreads. Однако, если имена пользователей изменяются, они не будут повторно излучаться. Если это важно, замените forkJoin на combineLatest и удалите оператора first из собранных наблюдаемых элементов.

+0

Спасибо, я буду работать над этой реализацией. Не знаю, важно ли еще указывать, что «участники» - это не то же самое, что «автор». В этом случае у меня есть ключ участника доступный мне в свойстве 'author' потока. Кроме того, я продолжаю видеть' $ {foo} 'в пути, но в документах нет ничего об этом. Является ли это просто сокращением для' ('/ path' + foo) '? –

+2

Это шаблоны шаблонов ES6: http: // stackoverflo w.com/questions/27565056/es6-template-literals-vs-concatenated-strings – cartant

+0

Мне пришлось исправить некоторые проблемы с скобками. Я думаю, что я избавился от правильных ... Я удалил блок участников, чтобы сосредоточиться на имени пользователя 'author' на данный момент. По какой-то причине, если я запишу 'memberObservables' в консоль после блока' forEach', я получаю массив пустых наблюдаемых. Я понимаю, что это потенциально глупое утверждение, потому что это может быть точка, но я полагаю, что я ожидаю, что блок 'forEach' будет заполнять этот массив. Я дам вам возможность ответить на этот вопрос до моего последнего вопроса относительно этого решения. –

0

Чтобы решить проблемы с подключением к пользователям, я написал службу, которая кэширует уже загруженных пользователей и отображает их в реферирующие данные с минимальным кодом.Он использует вложенную структуру карты, чтобы сделать присоединиться:

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); 
    } 
} 

Там же полный рабочий пример стыков и все шаблонные here

Смежные вопросы