javascript - Angular 從 ActivatedRoute 的 promise 在 Typescript await 中無法使用
要訪問當前 URL 路徑中的組件,在我的應用程序中以下方式可行:
constructor(private route: ActivatedRoute) { }
...
load() {
this.route.params.subscribe((params) => {
const id = +params['id'];
console.log('got parameter', id);
... etc
這是教科書上的範例,變數 id 如預期般被設定了。但我想使用更優雅的 await 形式卻行不通。(當然,我之後會有一連串的 await 語句。)像這樣:
async load() {
try {
console.log('getting parameters');
const params = await this.route.params.toPromise();
console.log('got params', params);
const id = +params['id'];
... etc
我得到的是第一次 console.log() 調用的輸出,但第二次從未出現。而且當然,id 變數沒有被設置,其餘的代碼也從未執行。
文件和運行中的程式碼都顯示 this.route.params 是一個 Observable,應該可以透過 toPromise() 轉換成 Promise,從而可以與 Typescript 的 async/await 一起使用。我在使用來自 HttpClient 模組的 Observables 時,使用 await 語句完全沒問題。
但是它不起作用。有人知道為什麼嗎?
答案#1
基本答案是:你在這裡遇到了無法控制的競態條件
當你訪問 Observable route.params 時,它尚未完成是很正常的。在這個時候對它調用 toPromise() 會導致一個長時間處於待定狀態的 Promise,這就是你所面臨的問題。
如果你不必使用這個 async await 結構,就不要使用它,而是最好通過 ActivatedRouteSnapshot 同步地直接訪問 params.id。
ngOnInit() {
const id: string = route.snapshot.params.id;
}
答案#2
關於 AlanObject 的問題 …為什麼 ActivatedRoute 一開始就使用 Observables…,原因是 ngOnInit() 只會在元件初始化時被呼叫,也就是元件被創建的時候。想像你的元件是用來顯示項目詳情,路由像是 /item/123,其中 123 是當前項目的 ID。
現在,如果你的元件還實作了 Previous 和 Next 連結,分別導向 /item/122 和 /item/124,該元件將不會被重新實例化。在這種情況下,你將需要訂閱或其他方式來獲取更新的 ID 和相關資料。
