From ea6b9afc3bbfeb2960adcc6bb0d2db021c8a33ae Mon Sep 17 00:00:00 2001 From: Oscar Lorentzon Date: Tue, 25 Oct 2016 11:22:20 +0200 Subject: [PATCH] Handle IO errors in components. --- src/component/NavigationComponent.ts | 9 +++- src/component/direction/DirectionComponent.ts | 9 +++- .../direction/DirectionDOMRenderer.ts | 21 ++++++-- .../imageplane/ImagePlaneComponent.ts | 48 +++++++++++++------ src/component/sequence/SequenceComponent.ts | 1 + src/component/sequence/SequenceDOMRenderer.ts | 16 +++++-- src/viewer/SpriteService.ts | 8 ++++ 7 files changed, 89 insertions(+), 23 deletions(-) diff --git a/src/component/NavigationComponent.ts b/src/component/NavigationComponent.ts index ad9cf166..3037d524 100644 --- a/src/component/NavigationComponent.ts +++ b/src/component/NavigationComponent.ts @@ -78,7 +78,14 @@ export class NavigationComponent extends Component { private _createVNode(direction: EdgeDirection, name: string): vd.VNode { return vd.h( `span.Direction.Direction${name}`, - {onclick: (ev: Event): void => { this._navigator.moveDir(direction).first().subscribe(); }}, + { + onclick: (ev: Event): void => { + this._navigator.moveDir(direction) + .subscribe( + (node: Node): void => { return; }, + (error: Error): void => { console.error(error); }); + }, + }, []); } } diff --git a/src/component/direction/DirectionComponent.ts b/src/component/direction/DirectionComponent.ts index a5e0f4f5..7624e2ba 100644 --- a/src/component/direction/DirectionComponent.ts +++ b/src/component/direction/DirectionComponent.ts @@ -137,7 +137,14 @@ export class DirectionComponent extends Component { return node.spatialEdges$ .withLatestFrom( configuration.distinguishSequence ? - this._navigator.newGraphService.cacheSequence$(node.sequenceKey) : + this._navigator.newGraphService + .cacheSequence$(node.sequenceKey) + .catch( + (error: Error, caught: Observable): Observable => { + console.error(`Failed to cache sequence (${node.sequenceKey})`, error); + + return Observable.empty(); + }) : Observable.of(null)); }) .subscribe( diff --git a/src/component/direction/DirectionDOMRenderer.ts b/src/component/direction/DirectionDOMRenderer.ts index b3d938ab..f56a461e 100644 --- a/src/component/direction/DirectionDOMRenderer.ts +++ b/src/component/direction/DirectionDOMRenderer.ts @@ -388,7 +388,12 @@ export class DirectionDOMRenderer { shiftVertically?: boolean): vd.VNode { let onClick: (e: Event) => void = - (e: Event): void => { navigator.moveToKey(key).subscribe(); }; + (e: Event): void => { + navigator.moveToKey(key) + .subscribe( + (node: Node): void => { return; }, + (error: Error): void => { console.error(error); }); + }; return this._createVNode( key, @@ -409,7 +414,12 @@ export class DirectionDOMRenderer { direction: EdgeDirection): vd.VNode { let onClick: (e: Event) => void = - (e: Event): void => { navigator.moveDir(direction).subscribe(); }; + (e: Event): void => { + navigator.moveDir(direction) + .subscribe( + (node: Node): void => { return; }, + (error: Error): void => { console.error(error); }); + }; return this._createVNode( key, @@ -428,7 +438,12 @@ export class DirectionDOMRenderer { direction: EdgeDirection): vd.VNode { let onClick: (e: Event) => void = - (e: Event): void => { navigator.moveDir(direction).subscribe(); }; + (e: Event): void => { + navigator.moveDir(direction) + .subscribe( + (node: Node): void => { return; }, + (error: Error): void => { console.error(error); }); + }; let style: any = { height: this._calculator.turnCircleSizeCss, diff --git a/src/component/imageplane/ImagePlaneComponent.ts b/src/component/imageplane/ImagePlaneComponent.ts index ce717abc..1984d4c1 100644 --- a/src/component/imageplane/ImagePlaneComponent.ts +++ b/src/component/imageplane/ImagePlaneComponent.ts @@ -117,7 +117,38 @@ export class ImagePlaneComponent extends Component { }) .subscribe(this._rendererOperation$); - this._nodeSubscription = this._navigator.stateService.currentNode$ + this._catchRecursively(this._highResRendererOperation(this._navigator.stateService.currentNode$)) + .subscribe(this._rendererOperation$); + } + + protected _deactivate(): void { + this._rendererDisposer$.next(null); + + this._rendererSubscription.unsubscribe(); + this._stateSubscription.unsubscribe(); + this._nodeSubscription.unsubscribe(); + } + + protected _getDefaultConfiguration(): IImagePlaneConfiguration { + return { maxPanoramaResolution: "none" }; + } + + private _catchRecursively(source$: Observable): + Observable { + return source$ + .catch( + (error: Error, caught: Observable): + Observable => { + console.error("Failed to fetch high res image", error); + + return this._catchRecursively( + this._highResRendererOperation( + this._navigator.stateService.currentNode$.skip(1))); + }); + } + + private _highResRendererOperation(node$: Observable): Observable { + return node$ .debounceTime(1000) .withLatestFrom( this._navigator.stateService.currentTransform$, @@ -182,20 +213,7 @@ export class ImagePlaneComponent extends Component { return renderer; }; - }) - .subscribe(this._rendererOperation$); - } - - protected _deactivate(): void { - this._rendererDisposer$.next(null); - - this._rendererSubscription.unsubscribe(); - this._stateSubscription.unsubscribe(); - this._nodeSubscription.unsubscribe(); - } - - protected _getDefaultConfiguration(): IImagePlaneConfiguration { - return { maxPanoramaResolution: "none" }; + }); } } diff --git a/src/component/sequence/SequenceComponent.ts b/src/component/sequence/SequenceComponent.ts index 23c2d2c4..0a2e39fe 100644 --- a/src/component/sequence/SequenceComponent.ts +++ b/src/component/sequence/SequenceComponent.ts @@ -422,6 +422,7 @@ export class SequenceComponent extends Component { this._navigator.stateService.appendNodes([node]); }, (error: Error): void => { + console.error(error); this.stop(); } ); diff --git a/src/component/sequence/SequenceDOMRenderer.ts b/src/component/sequence/SequenceDOMRenderer.ts index 33977d7f..54200d7a 100644 --- a/src/component/sequence/SequenceDOMRenderer.ts +++ b/src/component/sequence/SequenceDOMRenderer.ts @@ -8,7 +8,7 @@ import { SequenceDOMInteraction, } from "../../Component"; import {EdgeDirection} from "../../Edge"; -import {IEdgeStatus} from "../../Graph"; +import {IEdgeStatus, Node} from "../../Graph"; import {Navigator} from "../../Viewer"; export class SequenceDOMRenderer { @@ -119,7 +119,12 @@ export class SequenceDOMRenderer { let nextProperties: vd.createProperties = { onclick: nextKey != null ? - (e: Event): void => { navigator.moveDir(EdgeDirection.Next).subscribe(); } : + (e: Event): void => { + navigator.moveDir(EdgeDirection.Next) + .subscribe( + (node: Node): void => { return; }, + (error: Error): void => { console.error(error); }); + } : null, onmouseenter: (e: MouseEvent): void => { interaction.mouseEnterDirection$.next(EdgeDirection.Next); }, onmouseleave: (e: MouseEvent): void => { interaction.mouseLeaveDirection$.next(EdgeDirection.Next); }, @@ -130,7 +135,12 @@ export class SequenceDOMRenderer { let prevProperties: vd.createProperties = { onclick: prevKey != null ? - (e: Event): void => { navigator.moveDir(EdgeDirection.Prev).subscribe(); } : + (e: Event): void => { + navigator.moveDir(EdgeDirection.Prev) + .subscribe( + (node: Node): void => { return; }, + (error: Error): void => { console.error(error); }); + } : null, onmouseenter: (e: MouseEvent): void => { interaction.mouseEnterDirection$.next(EdgeDirection.Prev); }, onmouseleave: (e: MouseEvent): void => { interaction.mouseLeaveDirection$.next(EdgeDirection.Prev); }, diff --git a/src/viewer/SpriteService.ts b/src/viewer/SpriteService.ts index 4288b41e..34b9e605 100644 --- a/src/viewer/SpriteService.ts +++ b/src/viewer/SpriteService.ts @@ -216,6 +216,10 @@ export class SpriteService { image.src = window.URL.createObjectURL(blob); }; + imageXmlHTTP.onerror = (error: Event) => { + console.error(new Error(`Failed to fetch sprite sheet (${sprite}${format}.png)`)); + }; + imageXmlHTTP.send(); let jsonXmlHTTP: XMLHttpRequest = new XMLHttpRequest(); @@ -232,6 +236,10 @@ export class SpriteService { }); }; + jsonXmlHTTP.onerror = (error: Event) => { + console.error(new Error(`Failed to fetch sheet (${sprite}${format}.json)`)); + }; + jsonXmlHTTP.send(); }