Javascript angular 9同步执行代码隐藏中的订阅

Javascript angular 9同步执行代码隐藏中的订阅,javascript,angular,firebase,google-cloud-firestore,angularfire2,Javascript,Angular,Firebase,Google Cloud Firestore,Angularfire2,我需要运行一个有2个参数的方法,每个参数都是通过某种形式的subscribe函数得到的。第一个是从angular的页面路由通过url获得的集合。第二个是dokument,这是firebase的firestore文档 export class FirebaseDocument implements OnInit { collection: string; dokument: any; //== CONSTRUCTORS constructor( private ro

我需要运行一个有2个参数的方法,每个参数都是通过某种形式的subscribe函数得到的。第一个是从angular的页面路由通过url获得的集合。第二个是dokument,这是firebase的firestore文档

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.dokument仅在subscribe方法中填充

我需要在下一行运行时填充这个。console.log(this.dokument)


这让我目瞪口呆,因为两个subscribe方法使用的代码基本相同,但它们的行为方式不同。

有时一个subscribe可以是同步的。当
可观察的
ReplaySubject
a
BehaviorSubject
或具有
shareReplay()
管道的
可观察的
时,会发生这种情况。(可能还有其他选择

这将使observable在订阅时立即启动。但是,您不应指望这种行为,而应始终在订阅中继续。或者使用mergeMap之类的管道,并创建其他observable,您可以使用
async
管道在模板中访问它们

在您的例子中,
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);
    }); 
  }
}
导出类FirebaseDocument实现OnInit{
只读集合$:可观察=this.route.params.pipe(
映射((参数)=>参数集合)
);
只读文档$:Observable=this.db.collection(this.url).valueChanges().pipe(
shareReplay({refCount:true,bufferSize:1})
);
构造函数(私有路由:ActivatedRoute,私有db:AngularFirestore){}
恩戈尼尼特(){
//别忘了退订
组合测试([
此.集合$,
这个医生$
]).订阅((收藏、文档)=>{
此.doMultiParameterMethod(集合、文档);
}); 
}
}

也许你应该让可观察的东西成为一种承诺,在你的情况下应该是:

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

}
导出类FirebaseDocument实现OnInit{
集合:字符串;
dokument:任何;
//==构造函数
建造师(
专用路由:激活的路由,
私人数据库:AngularFirestore
) {}
//==初始化
恩戈尼尼特(){
log(“加载页面组件”);
this.route.params.subscribe(params=>{
this.collection=params[“collection”];
});
console.log(this.collection);//正确填充了集合
this.getDokument().then(docArr=>{
this.dokument=docArr[0];
this.doMultiParameterMethod(this.collection,this.dokument);
});
}
getDokument():承诺{
让itemsCollection=this.\u db.collection(url).valueChanges();
返回新承诺((解决、拒绝)=>{
itemsCollection.subscribe((响应:any)=>{
决心(回应);
},拒绝);
});
}
}

是否无法让数据库调用等待响应?强制它同步?我需要从文档中返回的数据在作为完全不同的对象提供给前端之前需要进行大量操作。除了您上面的建议之外,map函数来自何处?代码示例的第3行。在我做过的很多研究中,我似乎都是一个映射函数,但在每个复制的示例中,映射函数都会抛出一个错误。即使使用的导入与它们的工作示例相同