UNPKG

vim-webgl-component

Version:

A demonstration app built on top of the vim-webgl-viewer

149 lines (148 loc) 4.87 kB
"use strict"; /** * @module vim-ts */ Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoteBuffer = exports.setRemoteBufferMaxConcurency = void 0; const remoteValue_1 = require("./remoteValue"); const requestTracker_1 = require("./requestTracker"); const logging_1 = require("./logging"); let RemoteBufferMaxConcurency = 10; function setRemoteBufferMaxConcurency(value) { RemoteBufferMaxConcurency = value; } exports.setRemoteBufferMaxConcurency = setRemoteBufferMaxConcurency; class RetryRequest { constructor(url, range, // eslint-disable-next-line no-undef responseType) { this.url = url; this.range = range; this.responseType = responseType; } abort() { this.xhr.abort(); } send() { this.xhr?.abort(); const xhr = new XMLHttpRequest(); xhr.open('GET', this.url); xhr.responseType = this.responseType; if (this.range) { xhr.setRequestHeader('Range', this.range); } xhr.onprogress = (e) => { this.onProgress?.(e); }; xhr.onload = (e) => { this.onProgress?.(e); this.onLoad?.(xhr.response); }; xhr.onerror = (_) => { this.onError?.(); }; xhr.send(); this.xhr = xhr; } } /** * Wrapper to provide tracking for all webrequests via request logger. */ class RemoteBuffer { constructor(url, verbose = false) { this.maxConcurency = RemoteBufferMaxConcurency; this._queue = []; this._active = new Set(); this.url = url; this._logs = verbose ? new logging_1.DefaultLog() : new logging_1.NoLog(); this._tracker = new requestTracker_1.RequestTracker(url, this._logs); this._tracker.onUpdate = (p) => this.onProgress?.(p); this._encoded = new remoteValue_1.RemoteValue(() => this.requestEncoding()); } async requestEncoding() { const xhr = new XMLHttpRequest(); xhr.open('HEAD', this.url); xhr.send(); this._logs.log(`Requesting header for ${this.url}`); const promise = new Promise((resolve, reject) => { xhr.onload = (_) => { let encoding; try { encoding = xhr.getResponseHeader('content-encoding'); } catch (e) { this._logs.error(e); } resolve(encoding ?? undefined); }; xhr.onerror = (_) => resolve(undefined); }); const encoding = await promise; const encoded = !!encoding; this._logs.log(`Encoding for ${this.url} = ${encoding}`); if (encoded) { this._logs.log(`Defaulting to download strategy for encoded content at ${this.url}`); } return encoded; } abort() { this._active.forEach(request => { request.abort(); }); this._active.clear(); this._queue.length = 0; } async http(range, label) { const useRange = range && !(await this._encoded.get()); const rangeStr = useRange ? `bytes=${range.start}-${range.end - 1}` : undefined; const request = new RetryRequest(this.url, rangeStr, 'arraybuffer'); request.msg = useRange ? `${label} : [${range.start}, ${range.end}] of ${this.url}` : `${label} of ${this.url}`; this.enqueue(request); return new Promise((resolve, reject) => { this._tracker.start(label); request.onProgress = (e) => { this._tracker.update(label, e); }; request.onLoad = (result) => { this._tracker.end(label); resolve(result); this.end(request); }; request.onError = () => { this._tracker.fail(label); this.retry(request); }; }); } enqueue(xhr) { this._queue.push(xhr); this.next(); } retry(xhr) { this._active.delete(xhr); this.maxConcurency = Math.max(1, this.maxConcurency - 1); setTimeout(() => this.enqueue(xhr), 2000); } end(xhr) { this._active.delete(xhr); this.next(); } next() { if (this._queue.length === 0) { return; } if (this._active.size >= this.maxConcurency) { return; } const next = this._queue[0]; this._queue.shift(); this._active.add(next); next.send(); this._logs.log('Starting ' + next.msg); } } exports.RemoteBuffer = RemoteBuffer;