錯誤百科

應用程式持續不穩定

此警告只會在水合過程中出現在瀏覽器裡:當用戶端已啟用水合,但應用程式長時間(超過 10 秒)持續不穩定時,就會出現。

這通常發生在頁面上有一些待處理的微任務或巨集任務時。

Angular 水合仰賴 ApplicationRef.isStable 在應用程式內變得穩定時發出的訊號:

  • 在伺服器端渲染(SSR)期間,用來開始序列化程序
  • 在瀏覽器中,此訊號用來開始水合後的清理,移除未被認領而殘留的 DOM 節點

當 ApplicationRef.isStable 在 10 秒內沒有發出 true 時,就會顯示此警告。如果這是刻意的行為,且你的應用程式會在稍後穩定下來,你可以選擇忽略此警告。

使用 zone.js 的應用程式

使用 zone.js 的應用程式可能有各種因素導致穩定延遲。這些因素可能包括待處理的 HTTP 請求、計時器(setInterval、setTimeout),或持續呼叫 requestAnimationFrame 的邏輯。

巨集任務

巨集任務包括 setInterval、setTimeout、requestAnimationFrame 等函式。 如果在應用程式的初始化階段或在啟動的元件中呼叫了其中任何一個函式,都可能延遲應用程式變得穩定的時機。

@Component({
  selector: 'app',
  template: ``,
})
class Simple {
  constructor() {
    setInterval(() => { ... }, 1000)

    // or

    setTimeout(() => { ... }, 10_000)
  }
}

如果必須在初始化階段呼叫這些函式,在 Angular 區域之外呼叫它們即可解決問題:

class Simple {
  constructor() {
    const ngZone = inject(NgZone);

    ngZone.runOutsideAngular(() => {
      setInterval(() => {}, 1000);
    });
  }
}

第三方程式庫

有些第三方程式庫也會產生長時間執行的非同步任務,可能延遲應用程式的穩定。建議比照上述方式,在區域之外呼叫相關的程式庫程式碼。

在應用程式變得穩定後執行程式碼

你可以在應用程式變得穩定後,執行設定非同步任務的程式碼:

class Simple {
  constructor() {
    const applicationRef = inject(ApplicationRef);

    applicationRef.isStable.pipe( first((isStable) => isStable) ).subscribe(() => {
      // Note that we don't need to use `runOutsideAngular` because `isStable`
      // emits events outside of the Angular zone when it's truthy (falsy values
      // are emitted inside the Angular zone).
      setTimeout(() => { ... });
    });
  }
}

無區域應用程式

在無區域情境中,穩定延遲可能是由在無限迴圈中執行的 effect 內的應用程式程式碼(可能是因為 effect 函式中使用的訊號持續變化)或待處理的 HTTP 請求造成的。

開發人員也可以使用 PendingTasks 服務,明確參與標示應用程式的穩定性。如果你在應用程式中使用了上述 API,請確保有呼叫函式把任務標示為已完成。