Подпишитесь на наблюдаемое в сервисе сразу после его определения - PullRequest
0 голосов
/ 17 декабря 2018

В конструкторе службы Angular я создаю наблюдаемое, на которое мне нужно напрямую подписаться (без внутренней подписки).Как это сделать?В частности, в первом блоке кода ниже у меня есть переменная data.id .

this.current_trainee = this.db.collection('Users', ref => ref.where(
  'email', '==',  'EXAMPLE'  )).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Trainee;
      data.id = a.payload.doc.id;
      return data;
    });
  })
);

Теперь я хочу подписаться на нее напрямую, чтобы использовать ее в doc (data.id)"ниже:

 this.trainees = this.db.collection('Users').doc( data.id ).collection('Trainings_taken').snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Trainee;
      data.id = a.payload.doc.id;
      return data;
    });
  })
);

Я попытался подписаться на него следующим образом:

   this.current_trainee.subscribe(data => this.user_doc_id = data.id );

, где user_doc_id инициируется как пустая строка.Но это не работает, потому что user_doc_id остается пустой строкой. Любое предложение, пожалуйста? Спасибо заранее!

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Итак, в конце дня посмотрите ниже, что работает для меня.Это не очень элегантно, потому что часть кода повторяется, но это работает, и я хотел закрыть этот вопрос.Thx @ dream88!

this.current_trainee = this.db.collection('Users', ref => ref.where(
  'email', '==',  aux  )).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Trainee;
      data.id = a.payload.doc.id;
      return data;
    });
  })
  );

this.individual_trainings = this.db.collection('Users', ref => ref.where(
  'email', '==',  aux  )).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Trainee;
      data.id = a.payload.doc.id;
      return data;
    });
  }),
  switchMap((data) => {
    console.log(data);
    console.log(data[0].id);
    return this.aux2 = this.db.collection('Users').doc(data[0].id).collection('Trainings_taken').valueChanges();
  })
  );
0 голосов
/ 17 декабря 2018

Итак, основываясь на обсуждении, я сделал очень простой пример.Суть в том, что вам нужно связать ваш первый ответ (который дает вам data.id) и использовать его для непосредственного вызова второй функции БД (вместо использования 2 переменных).Причина, как я упоминал ранее, заключается в том, что вы делаете асинхронный вызов БД для получения вашего ID.Это произойдет в какой-то момент позже, и только тогда вы сможете позвонить, используя этот идентификатор.В вашем текущем коде вы просто вызываете функцию this.db.collection('Users').doc( data.id )..} немедленно, синхронно , которая не будет работать.

Я не использовал flatMap, поскольку у вас нетвнутренняя наблюдаемая (как мне показалось, случай)

import { of, Observable } from 'rxjs';
import { mergeMap,map } from 'rxjs/operators';

/**
 * Assume this is the response of the 
 * this.db.collection('Users', ref => ref.where(
 * 'email', '==',  'EXAMPLE'  )).snapshotChanges()
 * i.e an observable output 
 * and data_id is equivalent to data.id in your  
 */
const source = of({data_id: 0}, {data_id:1 },{data_id:2});

/**
 * Now if the data_id is the index to this array, in your case : you need the 
 * data.id to make a call to the `DB` to retrieve the trainees
 */
const db2 = ['a','b','c'];

//use map to get the ID you need and then directly call the db to retrieve trainees, in this case it will return you another observable
const example = source.pipe(map((e,i) =>  of(test(e.data_id))));

// subscribe to the observable and do your action
const subscribe = example.subscribe((val) => console.log(val));

function test(value) {
  return (db2[value]);
}

Stackblitz для вас, чтобы поиграть.

...