我需要运行一个有两个参数的方法,每个参数都是通过某种形式的订阅函数得到的。第一个是通过url从角的页面路由获得的集合。第二个是道具,这是消防队的消防队的文件。
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只在订阅方法中填充。
我需要在下一行运行时填充它。console.log(this.dokument);
我对此感到震惊,因为2订阅方法使用的代码本质上是相同的,但它们的行为方式不同。
发布于 2020-02-22 12:35:53
有时,订阅可以是同步的。当Observable是ReplaySubject、BehaviorSubject或有shareReplay()管道的Observable时,就会发生这种情况。(可能还有其他选择。
这将使可观察到的立即启动订阅。但是,您不应该指望这种行为,并且始终在您的订阅范围内继续。或者使用像mergeMap这样的管道,并创建其他可观察的对象,您可以使用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);
});
}
}发布于 2020-02-22 13:34:45
也许你应该做出一个可以观察到的承诺,在你的情况下,如下所示:
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);
});
}
}https://stackoverflow.com/questions/60352142
复制相似问题