UNPKG

@loaders.gl/loader-utils

Version:

Framework-independent loaders for 3D graphics formats

108 lines (94 loc) 2.92 kB
import { WorkerJob, WorkerMessageType, WorkerMessagePayload, isBrowser, WorkerFarm, getWorkerURL } from '@loaders.gl/worker-utils'; import type {Loader, LoaderOptions, LoaderContext} from '../../loader-types'; /** * Determines if a loader can parse with worker * @param loader * @param options */ export function canParseWithWorker(loader: Loader, options?: LoaderOptions) { if (!WorkerFarm.isSupported()) { return false; } // Node workers are still experimental if (!isBrowser && !options?._nodeWorkers) { return false; } return loader.worker && options?.worker; } /** * this function expects that the worker function sends certain messages, * this can be automated if the worker is wrapper by a call to createLoaderWorker in @loaders.gl/loader-utils. */ export async function parseWithWorker( loader: Loader, data: any, options?: LoaderOptions, context?: LoaderContext, parseOnMainThread?: (arrayBuffer: ArrayBuffer, options: {[key: string]: any}) => Promise<unknown> ) { const name = loader.id; // TODO const url = getWorkerURL(loader, options); const workerFarm = WorkerFarm.getWorkerFarm(options); const workerPool = workerFarm.getWorkerPool({name, url}); // options.log object contains functions which cannot be transferred // context.fetch & context.parse functions cannot be transferred // TODO - decide how to handle logging on workers options = JSON.parse(JSON.stringify(options)); context = JSON.parse(JSON.stringify(context || {})); const job = await workerPool.startJob( 'process-on-worker', // @ts-expect-error onMessage.bind(null, parseOnMainThread) // eslint-disable-line @typescript-eslint/no-misused-promises ); job.postMessage('process', { // @ts-ignore input: data, options, context }); const result = await job.result; // TODO - what is going on here? return await result.result; } /** * Handle worker's responses to the main thread * @param job * @param type * @param payload */ async function onMessage( parseOnMainThread: (arrayBuffer: ArrayBuffer, options?: {[key: string]: any}) => Promise<void>, job: WorkerJob, type: WorkerMessageType, payload: WorkerMessagePayload ) { switch (type) { case 'done': job.done(payload); break; case 'error': job.error(new Error(payload.error)); break; case 'process': // Worker is asking for main thread to parseO const {id, input, options} = payload; try { const result = await parseOnMainThread(input, options); job.postMessage('done', {id, result}); } catch (error) { const message = error instanceof Error ? error.message : 'unknown error'; job.postMessage('error', {id, error: message}); } break; default: // eslint-disable-next-line console.warn(`parse-with-worker unknown message ${type}`); } }