feat: add environment detection and threading utility functions
Introduced new utilities for detecting execution environments (browser, Node.js, Web Worker) and checking threading availability. Added `workerUtils` for executing functions in Web Workers or Worker Threads seamlessly based on the environment.
This commit is contained in:
parent
9e10caf604
commit
9ffc9d965e
2 changed files with 194 additions and 0 deletions
57
src/utils/environment.ts
Normal file
57
src/utils/environment.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Utility functions for environment detection
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check if code is running in a browser environment
|
||||
*/
|
||||
export function isBrowser(): boolean {
|
||||
return typeof window !== 'undefined' && typeof document !== 'undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if code is running in a Node.js environment
|
||||
*/
|
||||
export function isNode(): boolean {
|
||||
return typeof process !== 'undefined' &&
|
||||
process.versions != null &&
|
||||
process.versions.node != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if code is running in a Web Worker environment
|
||||
*/
|
||||
export function isWebWorker(): boolean {
|
||||
return typeof self === 'object' &&
|
||||
self.constructor &&
|
||||
self.constructor.name === 'DedicatedWorkerGlobalScope';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Web Workers are available in the current environment
|
||||
*/
|
||||
export function areWebWorkersAvailable(): boolean {
|
||||
return isBrowser() && typeof Worker !== 'undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Worker Threads are available in the current environment (Node.js)
|
||||
*/
|
||||
export function areWorkerThreadsAvailable(): boolean {
|
||||
if (!isNode()) return false;
|
||||
|
||||
try {
|
||||
// Dynamic import to avoid errors in browser environments
|
||||
require('worker_threads');
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if threading is available in the current environment
|
||||
*/
|
||||
export function isThreadingAvailable(): boolean {
|
||||
return areWebWorkersAvailable() || areWorkerThreadsAvailable();
|
||||
}
|
||||
137
src/utils/workerUtils.ts
Normal file
137
src/utils/workerUtils.ts
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* Utility functions for working with Web Workers and Worker Threads
|
||||
*/
|
||||
|
||||
import { isNode, isBrowser } from './environment.js';
|
||||
|
||||
/**
|
||||
* Execute a function in a Web Worker (browser environment)
|
||||
*
|
||||
* @param fn The function to execute
|
||||
* @param args The arguments to pass to the function
|
||||
* @returns A promise that resolves with the result of the function
|
||||
*/
|
||||
export function executeInWebWorker<T>(fn: Function, ...args: any[]): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Create a blob URL for the worker script
|
||||
const fnString = fn.toString();
|
||||
const workerScript = `
|
||||
self.onmessage = function(e) {
|
||||
try {
|
||||
const fn = ${fnString};
|
||||
const result = fn(...e.data);
|
||||
self.postMessage({ success: true, data: result });
|
||||
} catch (error) {
|
||||
self.postMessage({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
});
|
||||
}
|
||||
};
|
||||
`;
|
||||
|
||||
const blob = new Blob([workerScript], { type: 'application/javascript' });
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
|
||||
// Create a worker
|
||||
const worker = new Worker(blobURL);
|
||||
|
||||
// Set up message handling
|
||||
worker.onmessage = function(e: MessageEvent<{ success: boolean; data: T; error?: string }>) {
|
||||
URL.revokeObjectURL(blobURL); // Clean up
|
||||
worker.terminate(); // Terminate the worker
|
||||
|
||||
if (e.data.success) {
|
||||
resolve(e.data.data);
|
||||
} else {
|
||||
reject(new Error(e.data.error));
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = function(error: ErrorEvent) {
|
||||
URL.revokeObjectURL(blobURL); // Clean up
|
||||
worker.terminate(); // Terminate the worker
|
||||
reject(error);
|
||||
};
|
||||
|
||||
// Start the worker
|
||||
worker.postMessage(args);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a function in a Worker Thread (Node.js environment)
|
||||
*
|
||||
* @param fn The function to execute
|
||||
* @param args The arguments to pass to the function
|
||||
* @returns A promise that resolves with the result of the function
|
||||
*/
|
||||
export function executeInWorkerThread<T>(fn: Function, ...args: any[]): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// Dynamic import to avoid errors in browser environments
|
||||
const { Worker } = require('worker_threads');
|
||||
|
||||
// Create a worker script
|
||||
const fnString = fn.toString();
|
||||
const workerScript = `
|
||||
const { parentPort } = require('worker_threads');
|
||||
|
||||
parentPort.once('message', (data) => {
|
||||
try {
|
||||
const fn = ${fnString};
|
||||
const result = fn(...data);
|
||||
parentPort.postMessage({ success: true, data: result });
|
||||
} catch (error) {
|
||||
parentPort.postMessage({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
});
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
// Create a worker
|
||||
const worker = new Worker(workerScript, { eval: true });
|
||||
|
||||
// Set up message handling
|
||||
worker.on('message', (data: { success: boolean; data: T; error?: string }) => {
|
||||
worker.terminate(); // Terminate the worker
|
||||
|
||||
if (data.success) {
|
||||
resolve(data.data);
|
||||
} else {
|
||||
reject(new Error(data.error));
|
||||
}
|
||||
});
|
||||
|
||||
worker.on('error', (error: Error) => {
|
||||
worker.terminate(); // Terminate the worker
|
||||
reject(error);
|
||||
});
|
||||
|
||||
// Start the worker
|
||||
worker.postMessage(args);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a function in a separate thread based on the environment
|
||||
*
|
||||
* @param fn The function to execute
|
||||
* @param args The arguments to pass to the function
|
||||
* @returns A promise that resolves with the result of the function
|
||||
*/
|
||||
export function executeInThread<T>(fn: Function, ...args: any[]): Promise<T> {
|
||||
if (isBrowser()) {
|
||||
return executeInWebWorker<T>(fn, ...args);
|
||||
} else if (isNode()) {
|
||||
return executeInWorkerThread<T>(fn, ...args);
|
||||
} else {
|
||||
// Fall back to executing in the main thread
|
||||
return Promise.resolve(fn(...args) as T);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue