angular 9 выполнить подписку в коде синхронно - PullRequest
0 голосов
/ 22 февраля 2020

Мне нужно запустить метод с 2 параметрами, каждый параметр получен через некоторую форму функции подписки. первая - это коллекция, полученная через URL из angular маршрутизации страницы. Второй документ - это документ пожарной части пожарной базы.

export class FirebaseDocument implements OnInit {
   collection: string;
   dokument: any;

   //== CONSTRUCTORS
  constructor(
    private route: ActivatedRoute,
    private _db: AngularFirestore
  ) {}

  //== Initialize
  ngOnInit() {
    console.log("__loading page component");
    this.route.params.subscribe(params => {
      this.collection = params["collection"];
    });
    console.log(this.collection);//collection populated correctly

    //load the document from AngularFirestore
    console.log("loading the document from firebase");
    let itemsCollection = this._db.collection(url).valueChanges();

    //subscribe to get the dok of the first document in the collection
    itemsCollection.subscribe(docArr => {
        this.dokument = docArr[0];
        console.log(this.dokument);//dokument is populated
    });

    console.log(this.dokument);//dokument is undefined
    this.doMultiParameterMethod(this.collection, this.dokument);
  }
}

this.collection заполняется идеально; this.dokument заполняется только внутри метода подписки

Мне нужно, чтобы это заполнялось к моменту запуска следующей строки. the console.log (this.dokument);

Я был ошеломлен этим, потому что по сути один и тот же код используется двумя методами подписки, но они не ведут себя одинаково.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2020

Может быть, вы должны сделать Обязательное Обещание, в вашем случае будет следующее:

export class FirebaseDocument implements OnInit {
 collection: string;
 dokument: any;

 //== CONSTRUCTORS
 constructor(
  private route: ActivatedRoute,
  private _db: AngularFirestore
 ) {}

 //== Initialize
 ngOnInit() {
  console.log("__loading page component");
  this.route.params.subscribe(params => {
   this.collection = params["collection"];
  });

  console.log(this.collection); //collection populated correctly

  this.getDokument().then(docArr => {
   this.dokument = docArr[0];
   this.doMultiParameterMethod(this.collection, this.dokument);
  });

 }

 getDokument(): Promise<any> {
  let itemsCollection = this._db.collection(url).valueChanges();
  return new Promise((resolve, reject) => {
   itemsCollection.subscribe((response: any) => {
    resolve(response);
   }, reject);
  });
 }

}
0 голосов
/ 22 февраля 2020

Иногда подписка может быть синхронной. Это происходит, когда Observable является ReplaySubject a BehaviorSubject или Observable, у которого есть shareReplay() труба. (возможно, и другие варианты.

Это приведет к немедленному срабатыванию наблюдаемого при подписке. Однако вы никогда не должны рассчитывать на это поведение и всегда продолжать в рамках своей подписки. Или использовать каналы, такие как mergeMap, и создавать другие наблюдаемые. доступ к которому вы можете получить в своем шаблоне, используя async pipe.

В вашем случае. this.route.params, очевидно, является «воспроизводимой» наблюдаемой, из которой вы получаете последнее значение после подписки. В противном случае вам придется дождитесь повторного изменения параметров, пока не получите значение.

Ваш вызов базы данных не может вернуть немедленный ответ, потому что это по сути сетевой запрос.


В вашем примере кода вы можно обновить до этого и использовать async канал в вашем шаблоне

export class FirebaseDocument implements OnInit {
   readonly collection$: Observable<string> = this.route.params.pipe(
     map((params) => params.collection)
   );

   readonly doc$: Observable<any[]> = this.db.collection(this.url).valueChanges().pipe(
     shareReplay({ refCount: true, bufferSize: 1 })
   );

   constructor(private route: ActivatedRoute, private db: AngularFirestore) {}

  ngOnInit() {
    // don't forget to unsubscribe
    combineLatest([
      this.collection$,
      this.doc$
    ]).subscribe((collection, document) => {
      this.doMultiParameterMethod(collection, document);
    }); 
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...