/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/core/src/pending_tasks_internal.ts
91 строка
3 KB
Andrew Scott
feat(core): Add stability debugging utility
18 дек 2025, 02:43
18 дек 2025, 02:43
99ad18a
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import {BehaviorSubject, Observable} from 'rxjs'; import {ɵɵdefineInjectable} from './di/interface/defs'; import {OnDestroy} from './change_detection/lifecycle_hooks'; import {DEBUG_TASK_TRACKER} from './application/stability_debug'; import {inject} from './di'; /** * Internal implementation of the pending tasks service. */ export class PendingTasksInternal implements OnDestroy { private taskId = 0; private pendingTasks = new Set<number>(); private destroyed = false; private pendingTask = new BehaviorSubject<boolean>(false); private debugTaskTracker = inject(DEBUG_TASK_TRACKER, {optional: true}); get hasPendingTasks(): boolean { // Accessing the value of a closed `BehaviorSubject` throws an error. return this.destroyed ? false : this.pendingTask.value; } /** * In case the service is about to be destroyed, return a self-completing observable. * Otherwise, return the observable that emits the current state of pending tasks. */ get hasPendingTasksObservable(): Observable<boolean> { if (this.destroyed) { // Manually creating the observable pulls less symbols from RxJS than `of(false)`. return new Observable<boolean>((subscriber) => { subscriber.next(false); subscriber.complete(); }); } return this.pendingTask; } add(): number { // Emitting a value to a closed subject throws an error. if (!this.hasPendingTasks && !this.destroyed) { this.pendingTask.next(true); } const taskId = this.taskId++; this.pendingTasks.add(taskId); this.debugTaskTracker?.add(taskId); return taskId; } has(taskId: number): boolean { return this.pendingTasks.has(taskId); } remove(taskId: number): void { this.pendingTasks.delete(taskId); this.debugTaskTracker?.remove(taskId); if (this.pendingTasks.size === 0 && this.hasPendingTasks) { this.pendingTask.next(false); } } ngOnDestroy(): void { this.pendingTasks.clear(); if (this.hasPendingTasks) { this.pendingTask.next(false); } // We call `unsubscribe()` to release observers, as users may forget to // unsubscribe manually when subscribing to `isStable`. We do not call // `complete()` because it is unsafe; if someone subscribes using the `first` // operator and the observable completes before emitting a value, // RxJS will throw an error. this.destroyed = true; this.pendingTask.unsubscribe(); } /** @nocollapse */ static ɵprov = /** @pureOrBreakMyCode */ /* @__PURE__ */ ɵɵdefineInjectable({ token: PendingTasksInternal, providedIn: 'root', factory: () => new PendingTasksInternal(), }); }