[英]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.