網站搜尋

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 和相關資料。