Framework entegrasyonları · Angular + Three
Yükleme & OnDestroy: Ömürle Mühürlenen Kargo
Asenkron doku veya model, host ömründen uzun yaşarsa
sızıntı ve yarış üretir. Bu sayfa Angular'da yükleme ile
ngOnDestroy sahipliğini anlatır: Suspense dersi değil ·
Three varlık ↔ bileşen ömrü.
Holodepth bu yaprağı RxJS 101 veya R3F Suspense turunun kopyası olarak yazmaz. R3F asenkron köprü Yükleme & Suspense köprüsü yaprağındadır. Host ve şablon önceki Angular yapraklarındadır; kare Kare döngüsü & NgZone yaprağındadır. glTF alan spekü format izleklerinde; sıkıştırma Platform · Asset yaprağındadır. Dispose matematiği Three kaynak omurgasına linklenir.
Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Yük, bileşen ömrüne bağlıdır. Destroy önce biterse abonelik iptal edilir. OnDestroy registry geometri/materyal/doku/renderer salar. Paylaşılan cache ile yerel sahiplik ayrılır. URL değişince önceki yük iptal olur. Sonraki kapı pointer bağları & picking'tir.»
Bu sayfanın sınırı · komşu konularla ayrım
Bu sayfa Angular + Three'de yükleme / OnDestroy sahipliğini anlatır:
- Ömür pasaportu · yarış (destroy < load)
- Dispose registry · paylaşım vs yerel
- İptal / switchMap · hata yüzeyi
- Üç sahiplik profili
Bilinçli olarak dışarıda bırakılan konular:
- R3F useLoader / Suspense → R3F · Yükleme & Suspense
- Host / SSR → Host & kök
- NgZone rAF → Kare döngüsü & NgZone
- Pointer → Pointer bağları & picking
- Zone kaçışı → Zone kaçışı & performans
- RxJS / HttpClient 101 · glTF şema · Draco derinliği
Kısa ayrım: Bu sayfa «kargo ömürle nasıl mühürlenir?» · R3F yükleme «Suspense askı köprüsü» · NgZone «tik yaşarken» · Format «paket içinde ne var?».
Ömür pasaportu
Angular bileşeni doğar, view hazır olur, yok olur. Three Texture / BufferGeometry / Object3D ise GPU'da durur; Angular onları otomatik «çöp toplamaz». Holodepth: her asenkron kargonun pasaportu host veya parça bileşeninin ömrüne yazılır. Rota değişince pasaport düşer; kargo ya iptal edilir ya temiz salınır.
«Yükledim sahneye ekledim» yetmez. Ticket cümlesi: kim yükler, kim dispose eder, paylaşım var mı?
Ölü bileşenin canlı dokusu, sessiz bellek sızıntısıdır.
Yarış: destroy yükü geçer
Klasik hastalık: kullanıcı hızlı gezinir; Promise/Observable çözülünce
ölü bileşene scene.add veya setState benzeri
yazım yapılır. Holodepth: yük başlarken iptal jetonu alın
(takeUntilDestroyed, DestroyRef, veya
Subject complete). Çözüm geldiğinde jeton düşmüşse sahneye
dokunmayın; gelen kaynağı hemen dispose edin veya hiç kabul etmeyin.
Suspense modeli bu yarışı React ağacında askıyla çözer; Angular'da çözüm çoğunlukla iptal + guard'dır.
Yük yolları: Loader ve boru
Praxis'te iki yol yan yana durur: Three loader'ları (TextureLoader,
model loader…) ve Angular HttpClient + decode. Holodepth
şema açmaz: hangi yol seçilirse seçilsin, sonuç Object3D/Texture ömrü
OnDestroy'a bağlanır. Loader eklentileri (DRACO vb.) uygulama
bootstrap'ında bir kez kurulur; her bileşende yeniden yaratılmaz
(host sayfasındaki tek-kök ruhu).
URL değişince iptal
Input olarak asset URL'si değişince önceki indirme sürüyorsa
switchMap (veya eşdeğeri) eski akışı iptal eder; aksi hâlde
iki sonuç yarışır, yanlış doku kazanabilir. Holodepth: kimlik
(URL + sürüm) net; rastgele query ile cache delmek bilinçli busting
dışında yasaktır.
OnDestroy registry
Dağınık dispose() çağrıları unutulur. Holodepth pratikte
bir kaynak listesi tutar: geometri, materyal(ler), doku(lar),
opsiyonel RT / composer. ngOnDestroy listeyi gezip salar;
scene'den remove eder. Renderer host'a aittir (kök sayfa);
parça bileşen renderer'ı öldürmez.
| Model | Kim dispose eder? | Ne zaman? |
|---|---|---|
| Bileşen yerel | Yükleyen component | ngOnDestroy |
| Servis cache | Uygulama / bilinçli purge | Ömür boyu veya manuel |
| Misafir | Çağıran | Sözleşmeye göre |
Ortak materyali ilk çocuğun destroy'unda dispose etmek ikinci çocuğu öldürür. Cache modelinde dispose etmeyin.
Hata yüzeyi
404, CORS, bozuk buffer sessiz siyah sahne üretebilir. Angular'da hata
catchError / şablon bayrağı / kullanıcı mesajı ile yüzeye
çıkar. React Error Boundary kopyası değildir; ürün standardı: reject
yutulmaz. Kullanıcı URL'sini doğrulamadan loader'a vermeyin.
Decode'u rAF'e gömmeyin
NgZone yaprağı tiki ince tutmayı mühürledi. Fetch + parse + texture upload'u her kareye yaymak jank üretir. Yük askı / Promise yolunda bitsin; yerleşince demand veya sürekli loop bir kare boyasın. Platform FPS dilim teşhisine köprüdır.
Yükleme şeridi ile kare şeridi ayrı metronomdur.
Güvenli ömür: simüle kargo
Örnekler öğretim amaçlıdır. RxJS operatör varyantları tam müfredat değildir; sabit allowlist URL kullanın.
Simüle · TextureLoader + takeUntilDestroyed.
import {
Component, DestroyRef, Input, OnChanges, OnDestroy, SimpleChanges, inject,
} from '@angular/core'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
import { Observable, from } from 'rxjs'
import * as THREE from 'three'
const PANEL_MAP = '/assets/demo/panel-albedo.jpg' // allowlist · kullanıcı string'i yok
function loadTexture$(url: string): Observable<THREE.Texture> {
return from(
new Promise<THREE.Texture>((resolve, reject) => {
new THREE.TextureLoader().load(url, resolve, undefined, reject)
}),
)
}
@Component({
selector: 'app-panel-texture',
template: '',
})
export class PanelTextureComponent implements OnChanges, OnDestroy {
@Input({ required: true }) parent!: THREE.Object3D
private readonly destroyRef = inject(DestroyRef)
private mesh?: THREE.Mesh
private map?: THREE.Texture
private readonly mat = new THREE.MeshStandardMaterial({ roughness: 0.55, metalness: 0.05 })
ngOnChanges(changes: SimpleChanges): void {
if (!this.parent || this.mesh) return
// Eğitim: URL sabit. Dinamik URL'de switchMap + iptal kullanın.
loadTexture$(PANEL_MAP)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (tex) => {
tex.colorSpace = THREE.SRGBColorSpace
this.map = tex
this.mat.map = tex
this.mat.needsUpdate = true
this.mesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 1.25), this.mat)
this.parent.add(this.mesh)
},
error: () => {
// Üründe kullanıcıya görünür hata yüzeyi
},
})
}
ngOnDestroy(): void {
if (this.mesh) {
this.parent?.remove(this.mesh)
this.mesh.geometry.dispose()
this.mesh = undefined
}
this.mat.dispose()
this.map?.dispose()
this.map = undefined
}
}
Simüle · sahiplik notlu registry.
/** Yerel sahiplik · cache paylaşımında track etmeyin */
export class DisposeRegistry {
private readonly geos = []
private readonly mats = []
private readonly maps = []
trackGeo(g) { this.geos.push(g); return g }
trackMat(m) { this.mats.push(m); return m }
trackMap(t) { this.maps.push(t); return t }
disposeAll() {
for (const g of this.geos) g.dispose?.()
for (const m of this.mats) {
if (Array.isArray(m)) m.forEach((x) => x.dispose?.())
else m.dispose?.()
}
for (const t of this.maps) t.dispose?.()
this.geos.length = 0
this.mats.length = 0
this.maps.length = 0
}
}
/**
* ngOnDestroy:
* this.scene.remove(this.root)
* this.registry.disposeAll()
* Renderer'ı burada öldürmeyin · host'a aittir.
*/
Güvenlik: allowlist yolları; origin kontrolü; hata mesajında dahili yol sızdırmayın; bozuk dosyayı başarılı saymayın.
Yükleme / destroy tuzakları
- Guard yok: ölüye add.
- URL yarışı: switchMap unutuldu.
- Ortak mat dispose: komşu ölür.
- Renderer child destroy: host'u kırar.
- rAF içi decode: jank.
- Sessiz catch: siyah sahne.
- Suspense ezberi: Angular'da aynı API yok.
Üç sahiplik profili
-
01 · Kargo
Vitrin kahramanı
- Sahiplik
- Bileşen yerel registry
- İptal
- takeUntilDestroyed
- Risk
- Hızlı rota yarışı
-
02 · Kargo
Paylaşılan kütüphane
- Sahiplik
- Servis cache
- Dispose
- İlk unmount'ta kesme
- Risk
- Ömür boyu şişme
-
03 · Kargo
Dinamik URL paneli
- Akış
- switchMap + allowlist
- UI
- Hata yüzeyi zorunlu
- Risk
- Önceki dokunun geç gelmesi
Holodepth perspektifleri
Ömür = yetki
Destroy düşmüşse kargo sahneye yazılmaz.
Registry yazın
Dağınık dispose unutulur; liste unutulmaz.
Paylaşımı etiketleyin
Cache ise dispose etme; yerel ise et.
Teşhis maddeleri
- takeUntilDestroyed / iptal var mı?
- URL değişiminde switchMap var mı?
- Sahiplik modeli yazılı mı?
- Registry geometri/mat/doku kapsıyor mu?
- Renderer yanlışlıkla child'da mı ölüyor?
- Hata yüzeyi sessiz mi?
- Decode rAF içinde mi?
- Suspense veya glTF şema bu sayfaya sızmış mı?
Holodepth içgörüsü
«Model geldi sonra patladı» çoğu zaman format değil; yarış veya yanlış dispose'tur. Önce ömür pasaportunu okuyun.
Sonraki kapı: pointer bağları
Kargo yerleşince kullanıcı dokunur. Sonraki sayfa Pointer bağları & picking Angular olay bağları ile Three isabetini anlatır. Zone kaçışı son yapraktadır.