opnet
Version:
The perfect library for building Bitcoin-based applications.
92 lines (91 loc) • 3.34 kB
JavaScript
import { BaseThreader } from './SharedThreader.js';
import { jsonWorkerScript } from './worker-scripts/JSONWorker.js';
let _isServiceWorker = null;
function checkIsServiceWorker() {
if (_isServiceWorker !== null)
return _isServiceWorker;
if (typeof __IS_SERVICE_WORKER__ !== 'undefined' && __IS_SERVICE_WORKER__) {
_isServiceWorker = true;
return true;
}
if (typeof ServiceWorkerGlobalScope !== 'undefined' &&
self instanceof ServiceWorkerGlobalScope) {
_isServiceWorker = true;
return true;
}
_isServiceWorker = false;
return false;
}
const isServiceWorker = checkIsServiceWorker();
export class JsonThreader extends BaseThreader {
workerScript = jsonWorkerScript;
threadingThreshold;
constructor(options = {}) {
super(options);
this.threadingThreshold = options.threadingThreshold ?? 16_384;
}
async parse(json) {
if (isServiceWorker || json.length < this.threadingThreshold) {
return JSON.parse(json);
}
const result = await this.run('parse', json);
return result;
}
async parseBuffer(buffer) {
if (isServiceWorker || buffer.byteLength <= this.threadingThreshold) {
const text = new TextDecoder().decode(buffer);
return JSON.parse(text);
}
const result = await this.runWithTransfer('parse', buffer, [buffer]);
return result;
}
async stringify(data) {
const result = JSON.stringify(data);
if (isServiceWorker || result.length < this.threadingThreshold) {
return result;
}
return (await this.run('stringify', data));
}
async fetch(request) {
if (isServiceWorker) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), request.timeout || 20_000);
try {
const resp = await fetch(request.url, {
method: 'POST',
headers: request.headers || {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(request.payload),
signal: controller.signal,
});
clearTimeout(timeoutId);
if (!resp.ok) {
throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
}
return (await resp.json());
}
catch (err) {
clearTimeout(timeoutId);
if (err.name === 'AbortError') {
throw new Error(`Request timed out after ${request.timeout || 20_000}ms`, {
cause: err,
});
}
throw err;
}
}
const result = await this.run('fetch', request);
return result;
}
}
const GLOBAL_KEY = Symbol.for('opnet.jsonThreader');
const globalObj = (typeof globalThis !== 'undefined' ? globalThis : global);
if (!(GLOBAL_KEY in globalObj)) {
globalObj[GLOBAL_KEY] = new JsonThreader();
}
export function initJsonThreader() {
return Promise.resolve(globalObj[GLOBAL_KEY]);
}
export const jsonThreader = globalObj[GLOBAL_KEY];