Merge pull request #5713 from mempool/mononaut/fix-missing-unsubs
clean up subscriptions & component references
This commit is contained in:
commit
c3686a5500
@ -46,6 +46,8 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
|
|
||||||
aggregatedHistory$: Observable<any>;
|
aggregatedHistory$: Observable<any>;
|
||||||
statsSubscription: Subscription;
|
statsSubscription: Subscription;
|
||||||
|
aggregatedHistorySubscription: Subscription;
|
||||||
|
fragmentSubscription: Subscription;
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
formatNumber = formatNumber;
|
formatNumber = formatNumber;
|
||||||
timespan = '';
|
timespan = '';
|
||||||
@ -80,7 +82,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
|
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
|
||||||
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
||||||
|
|
||||||
this.route.fragment.subscribe((fragment) => {
|
this.fragmentSubscription = this.route.fragment.subscribe((fragment) => {
|
||||||
if (['24h', '3d', '1w', '1m', '3m', 'all'].indexOf(fragment) > -1) {
|
if (['24h', '3d', '1w', '1m', '3m', 'all'].indexOf(fragment) > -1) {
|
||||||
this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
|
this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
|
||||||
}
|
}
|
||||||
@ -113,7 +115,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
share(),
|
share(),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.aggregatedHistory$.subscribe();
|
this.aggregatedHistorySubscription = this.aggregatedHistory$.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
@ -335,8 +337,8 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.statsSubscription) {
|
this.aggregatedHistorySubscription?.unsubscribe();
|
||||||
this.statsSubscription.unsubscribe();
|
this.fragmentSubscription?.unsubscribe();
|
||||||
}
|
this.statsSubscription?.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,13 +172,19 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.animationFrameRequest) {
|
if (this.animationFrameRequest) {
|
||||||
cancelAnimationFrame(this.animationFrameRequest);
|
cancelAnimationFrame(this.animationFrameRequest);
|
||||||
clearTimeout(this.animationHeartBeat);
|
|
||||||
}
|
}
|
||||||
|
clearTimeout(this.animationHeartBeat);
|
||||||
if (this.canvas) {
|
if (this.canvas) {
|
||||||
this.canvas.nativeElement.removeEventListener('webglcontextlost', this.handleContextLost);
|
this.canvas.nativeElement.removeEventListener('webglcontextlost', this.handleContextLost);
|
||||||
this.canvas.nativeElement.removeEventListener('webglcontextrestored', this.handleContextRestored);
|
this.canvas.nativeElement.removeEventListener('webglcontextrestored', this.handleContextRestored);
|
||||||
this.themeChangedSubscription?.unsubscribe();
|
|
||||||
}
|
}
|
||||||
|
if (this.scene) {
|
||||||
|
this.scene.destroy();
|
||||||
|
}
|
||||||
|
this.vertexArray.destroy();
|
||||||
|
this.vertexArray = null;
|
||||||
|
this.themeChangedSubscription?.unsubscribe();
|
||||||
|
this.searchSubscription?.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(direction): void {
|
clear(direction): void {
|
||||||
@ -447,7 +453,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
}
|
}
|
||||||
this.applyQueuedUpdates();
|
this.applyQueuedUpdates();
|
||||||
// skip re-render if there's no change to the scene
|
// skip re-render if there's no change to the scene
|
||||||
if (this.scene && this.gl) {
|
if (this.scene && this.gl && this.vertexArray) {
|
||||||
/* SET UP SHADER UNIFORMS */
|
/* SET UP SHADER UNIFORMS */
|
||||||
// screen dimensions
|
// screen dimensions
|
||||||
this.gl.uniform2f(this.gl.getUniformLocation(this.shaderProgram, 'screenSize'), this.displayWidth, this.displayHeight);
|
this.gl.uniform2f(this.gl.getUniformLocation(this.shaderProgram, 'screenSize'), this.displayWidth, this.displayHeight);
|
||||||
@ -489,9 +495,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
if (this.running && this.scene && now <= (this.scene.animateUntil + 500)) {
|
if (this.running && this.scene && now <= (this.scene.animateUntil + 500)) {
|
||||||
this.doRun();
|
this.doRun();
|
||||||
} else {
|
} else {
|
||||||
if (this.animationHeartBeat) {
|
|
||||||
clearTimeout(this.animationHeartBeat);
|
clearTimeout(this.animationHeartBeat);
|
||||||
}
|
|
||||||
this.animationHeartBeat = window.setTimeout(() => {
|
this.animationHeartBeat = window.setTimeout(() => {
|
||||||
this.start();
|
this.start();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -19,6 +19,7 @@ export class FastVertexArray {
|
|||||||
freeSlots: number[];
|
freeSlots: number[];
|
||||||
lastSlot: number;
|
lastSlot: number;
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
destroyed = false;
|
||||||
|
|
||||||
constructor(length, stride) {
|
constructor(length, stride) {
|
||||||
this.length = length;
|
this.length = length;
|
||||||
@ -32,6 +33,9 @@ export class FastVertexArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
insert(sprite: TxSprite): number {
|
insert(sprite: TxSprite): number {
|
||||||
|
if (this.destroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.count++;
|
this.count++;
|
||||||
|
|
||||||
let position;
|
let position;
|
||||||
@ -45,11 +49,14 @@ export class FastVertexArray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.sprites[position] = sprite;
|
this.sprites[position] = sprite;
|
||||||
return position;
|
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(index: number): void {
|
remove(index: number): void {
|
||||||
|
if (this.destroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.count--;
|
this.count--;
|
||||||
this.clearData(index);
|
this.clearData(index);
|
||||||
this.freeSlots.push(index);
|
this.freeSlots.push(index);
|
||||||
@ -61,20 +68,26 @@ export class FastVertexArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setData(index: number, dataChunk: number[]): void {
|
setData(index: number, dataChunk: number[]): void {
|
||||||
|
if (this.destroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.data.set(dataChunk, (index * this.stride));
|
this.data.set(dataChunk, (index * this.stride));
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearData(index: number): void {
|
private clearData(index: number): void {
|
||||||
this.data.fill(0, (index * this.stride), ((index + 1) * this.stride));
|
this.data.fill(0, (index * this.stride), ((index + 1) * this.stride));
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(index: number): Float32Array {
|
getData(index: number): Float32Array {
|
||||||
|
if (this.destroyed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return this.data.subarray(index, this.stride);
|
return this.data.subarray(index, this.stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
expand(): void {
|
private expand(): void {
|
||||||
this.length *= 2;
|
this.length *= 2;
|
||||||
const newData = new Float32Array(this.length * this.stride);
|
const newData = new Float32Array(this.length * this.stride);
|
||||||
newData.set(this.data);
|
newData.set(this.data);
|
||||||
@ -82,7 +95,7 @@ export class FastVertexArray {
|
|||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
compact(): void {
|
private compact(): void {
|
||||||
// New array length is the smallest power of 2 larger than the sprite count (but no smaller than 512)
|
// New array length is the smallest power of 2 larger than the sprite count (but no smaller than 512)
|
||||||
const newLength = Math.max(512, Math.pow(2, Math.ceil(Math.log2(this.count))));
|
const newLength = Math.max(512, Math.pow(2, Math.ceil(Math.log2(this.count))));
|
||||||
if (newLength !== this.length) {
|
if (newLength !== this.length) {
|
||||||
@ -110,4 +123,13 @@ export class FastVertexArray {
|
|||||||
getVertexData(): Float32Array {
|
getVertexData(): Float32Array {
|
||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroy(): void {
|
||||||
|
this.data = null;
|
||||||
|
this.sprites = null;
|
||||||
|
this.freeSlots = null;
|
||||||
|
this.lastSlot = 0;
|
||||||
|
this.dirty = false;
|
||||||
|
this.destroyed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ export class BlockViewComponent implements OnInit, OnDestroy {
|
|||||||
this.isLoadingBlock = false;
|
this.isLoadingBlock = false;
|
||||||
this.isLoadingOverview = true;
|
this.isLoadingOverview = true;
|
||||||
}),
|
}),
|
||||||
shareReplay(1)
|
shareReplay({ bufferSize: 1, refCount: true })
|
||||||
);
|
);
|
||||||
|
|
||||||
this.overviewSubscription = block$.pipe(
|
this.overviewSubscription = block$.pipe(
|
||||||
@ -176,5 +176,8 @@ export class BlockViewComponent implements OnInit, OnDestroy {
|
|||||||
if (this.queryParamsSubscription) {
|
if (this.queryParamsSubscription) {
|
||||||
this.queryParamsSubscription.unsubscribe();
|
this.queryParamsSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
if (this.blockGraph) {
|
||||||
|
this.blockGraph.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
|
|||||||
this.openGraphService.waitOver('block-data-' + this.rawId);
|
this.openGraphService.waitOver('block-data-' + this.rawId);
|
||||||
}),
|
}),
|
||||||
throttleTime(50, asyncScheduler, { leading: true, trailing: true }),
|
throttleTime(50, asyncScheduler, { leading: true, trailing: true }),
|
||||||
shareReplay(1)
|
shareReplay({ bufferSize: 1, refCount: true })
|
||||||
);
|
);
|
||||||
|
|
||||||
this.overviewSubscription = block$.pipe(
|
this.overviewSubscription = block$.pipe(
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Component, OnInit, OnDestroy, ViewChildren, QueryList, ChangeDetectorRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChildren, QueryList, ChangeDetectorRef } from '@angular/core';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
import { ActivatedRoute, ParamMap, Params, Router } from '@angular/router';
|
||||||
import { ElectrsApiService } from '@app/services/electrs-api.service';
|
import { ElectrsApiService } from '@app/services/electrs-api.service';
|
||||||
import { switchMap, tap, throttleTime, catchError, map, shareReplay, startWith, filter } from 'rxjs/operators';
|
import { switchMap, tap, throttleTime, catchError, map, shareReplay, startWith, filter, take } from 'rxjs/operators';
|
||||||
import { Observable, of, Subscription, asyncScheduler, EMPTY, combineLatest, forkJoin } from 'rxjs';
|
import { Observable, of, Subscription, asyncScheduler, EMPTY, combineLatest, forkJoin } from 'rxjs';
|
||||||
import { StateService } from '@app/services/state.service';
|
import { StateService } from '@app/services/state.service';
|
||||||
import { SeoService } from '@app/services/seo.service';
|
import { SeoService } from '@app/services/seo.service';
|
||||||
@ -68,6 +68,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
paginationMaxSize = window.matchMedia('(max-width: 670px)').matches ? 3 : 5;
|
paginationMaxSize = window.matchMedia('(max-width: 670px)').matches ? 3 : 5;
|
||||||
numUnexpected: number = 0;
|
numUnexpected: number = 0;
|
||||||
mode: 'projected' | 'actual' = 'projected';
|
mode: 'projected' | 'actual' = 'projected';
|
||||||
|
currentQueryParams: Params;
|
||||||
|
|
||||||
overviewSubscription: Subscription;
|
overviewSubscription: Subscription;
|
||||||
accelerationsSubscription: Subscription;
|
accelerationsSubscription: Subscription;
|
||||||
@ -80,8 +81,8 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
timeLtr: boolean;
|
timeLtr: boolean;
|
||||||
childChangeSubscription: Subscription;
|
childChangeSubscription: Subscription;
|
||||||
auditPrefSubscription: Subscription;
|
auditPrefSubscription: Subscription;
|
||||||
|
isAuditEnabledSubscription: Subscription;
|
||||||
oobSubscription: Subscription;
|
oobSubscription: Subscription;
|
||||||
|
|
||||||
priceSubscription: Subscription;
|
priceSubscription: Subscription;
|
||||||
blockConversion: Price;
|
blockConversion: Price;
|
||||||
|
|
||||||
@ -118,7 +119,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
this.setAuditAvailable(this.auditSupported);
|
this.setAuditAvailable(this.auditSupported);
|
||||||
|
|
||||||
if (this.auditSupported) {
|
if (this.auditSupported) {
|
||||||
this.isAuditEnabledFromParam().subscribe(auditParam => {
|
this.isAuditEnabledSubscription = this.isAuditEnabledFromParam().subscribe(auditParam => {
|
||||||
if (this.auditParamEnabled) {
|
if (this.auditParamEnabled) {
|
||||||
this.auditModeEnabled = auditParam;
|
this.auditModeEnabled = auditParam;
|
||||||
} else {
|
} else {
|
||||||
@ -281,7 +282,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
throttleTime(300, asyncScheduler, { leading: true, trailing: true }),
|
throttleTime(300, asyncScheduler, { leading: true, trailing: true }),
|
||||||
shareReplay(1)
|
shareReplay({ bufferSize: 1, refCount: true })
|
||||||
);
|
);
|
||||||
|
|
||||||
this.overviewSubscription = this.block$.pipe(
|
this.overviewSubscription = this.block$.pipe(
|
||||||
@ -363,6 +364,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
.subscribe((network) => this.network = network);
|
.subscribe((network) => this.network = network);
|
||||||
|
|
||||||
this.queryParamsSubscription = this.route.queryParams.subscribe((params) => {
|
this.queryParamsSubscription = this.route.queryParams.subscribe((params) => {
|
||||||
|
this.currentQueryParams = params;
|
||||||
if (params.showDetails === 'true') {
|
if (params.showDetails === 'true') {
|
||||||
this.showDetails = true;
|
this.showDetails = true;
|
||||||
} else {
|
} else {
|
||||||
@ -414,6 +416,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.stateService.markBlock$.next({});
|
this.stateService.markBlock$.next({});
|
||||||
this.overviewSubscription?.unsubscribe();
|
this.overviewSubscription?.unsubscribe();
|
||||||
|
this.accelerationsSubscription?.unsubscribe();
|
||||||
this.keyNavigationSubscription?.unsubscribe();
|
this.keyNavigationSubscription?.unsubscribe();
|
||||||
this.blocksSubscription?.unsubscribe();
|
this.blocksSubscription?.unsubscribe();
|
||||||
this.cacheBlocksSubscription?.unsubscribe();
|
this.cacheBlocksSubscription?.unsubscribe();
|
||||||
@ -421,8 +424,16 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
this.queryParamsSubscription?.unsubscribe();
|
this.queryParamsSubscription?.unsubscribe();
|
||||||
this.timeLtrSubscription?.unsubscribe();
|
this.timeLtrSubscription?.unsubscribe();
|
||||||
this.childChangeSubscription?.unsubscribe();
|
this.childChangeSubscription?.unsubscribe();
|
||||||
this.priceSubscription?.unsubscribe();
|
this.auditPrefSubscription?.unsubscribe();
|
||||||
|
this.isAuditEnabledSubscription?.unsubscribe();
|
||||||
this.oobSubscription?.unsubscribe();
|
this.oobSubscription?.unsubscribe();
|
||||||
|
this.priceSubscription?.unsubscribe();
|
||||||
|
this.blockGraphProjected.forEach(graph => {
|
||||||
|
graph.destroy();
|
||||||
|
});
|
||||||
|
this.blockGraphActual.forEach(graph => {
|
||||||
|
graph.destroy();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - Refactor this.fees/this.reward for liquid because it is not
|
// TODO - Refactor this.fees/this.reward for liquid because it is not
|
||||||
@ -733,8 +744,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
toggleAuditMode(): void {
|
toggleAuditMode(): void {
|
||||||
this.stateService.hideAudit.next(this.auditModeEnabled);
|
this.stateService.hideAudit.next(this.auditModeEnabled);
|
||||||
|
|
||||||
this.route.queryParams.subscribe(params => {
|
const queryParams = { ...this.currentQueryParams };
|
||||||
const queryParams = { ...params };
|
|
||||||
delete queryParams['audit'];
|
delete queryParams['audit'];
|
||||||
|
|
||||||
let newUrl = this.router.url.split('?')[0];
|
let newUrl = this.router.url.split('?')[0];
|
||||||
@ -742,10 +752,10 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
if (queryString) {
|
if (queryString) {
|
||||||
newUrl += '?' + queryString;
|
newUrl += '?' + queryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.location.replaceState(newUrl);
|
this.location.replaceState(newUrl);
|
||||||
});
|
|
||||||
|
|
||||||
|
// avoid duplicate subscriptions
|
||||||
|
this.auditPrefSubscription?.unsubscribe();
|
||||||
this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => {
|
this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => {
|
||||||
this.auditModeEnabled = !hide;
|
this.auditModeEnabled = !hide;
|
||||||
this.showAudit = this.auditAvailable && this.auditModeEnabled;
|
this.showAudit = this.auditAvailable && this.auditModeEnabled;
|
||||||
|
@ -162,6 +162,9 @@ export class EightBlocksComponent implements OnInit, OnDestroy {
|
|||||||
this.cacheBlocksSubscription?.unsubscribe();
|
this.cacheBlocksSubscription?.unsubscribe();
|
||||||
this.networkChangedSubscription?.unsubscribe();
|
this.networkChangedSubscription?.unsubscribe();
|
||||||
this.queryParamsSubscription?.unsubscribe();
|
this.queryParamsSubscription?.unsubscribe();
|
||||||
|
this.blockGraphs.forEach(graph => {
|
||||||
|
graph.destroy();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
shiftTestBlocks(): void {
|
shiftTestBlocks(): void {
|
||||||
|
@ -120,6 +120,7 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
this.blockGraph?.destroy();
|
||||||
this.blockSub.unsubscribe();
|
this.blockSub.unsubscribe();
|
||||||
this.timeLtrSubscription.unsubscribe();
|
this.timeLtrSubscription.unsubscribe();
|
||||||
this.websocketService.stopTrackMempoolBlock();
|
this.websocketService.stopTrackMempoolBlock();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user