[英]angular 9 execute subscribe in code behind synchronously
我需要运行一个带有 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.collection 可以很好地填充; this.dokument 仅填充在 subscribe 方法中
我需要在下一行运行时填充它。 console.log(this.dokument);
我对此感到目瞪口呆,因为 2 种订阅方法使用的代码基本上相同,但它们的行为方式不同。
有时订阅可以是同步的。 这种情况发生在Observable
是ReplaySubject
一个BehaviorSubject
或Observable
具有shareReplay()
管。 (可能还有其他选择。
这将使 observable 在订阅时立即触发。 但是,您永远不应该指望这种行为,并始终在您的订阅中继续.. 或者使用像 mergeMap 这样的管道并创建其他可观察对象,您可以使用async
管道在模板中访问它们。
在你的情况下。 this.route.params
显然是一个“重播” Observable,您可以在订阅后从中获得最新值。 否则,您将不得不等待参数再次更改,直到获得值。
您的 Database 调用无法立即返回响应,因为它本质上是一个网络请求。
在您的示例代码中,您可以将其更新为此,并在您的模板中使用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);
});
}
}
也许你应该让 Observable 成为一个 Promise,在你的情况下是这样的:
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);
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.