Elysia Tools

在一个清晰的工作台里浏览工具、案例、可视化和主题指南。

热门分类

专题

语言
ZHESPTRUFRDEEN

Elysia Tools

导航

TypeScript

Web TypeScript 多线程编程示例

Web TypeScript 多线程编程示例,包括Web Workers、异步操作和并行处理

案例

这个案例集合中的条目

代码typescript中等

Web Workers

创建和使用Web Workers在浏览器环境中进行并行执行

难度

6/10

预计时间

30 min

标签

typescript, web, multithreading

前置条件

Intermediate TypeScript, Web Workers API

typescript
// Web TypeScript Web Workers Examples
// Using Web Workers for parallel execution and background processing

// 1. Basic Web Worker Creation
class WorkerManager {
  private workers: Map<string, Worker> = new Map();

  // Create inline worker from code
  createInlineWorker(name: string, workerCode: string): Worker {
    const blob = new Blob([workerCode], { type: 'application/javascript' });
    const workerUrl = URL.createObjectURL(blob);
    const worker = new Worker(workerUrl);

    this.workers.set(name, worker);
    return worker;
  }

  // Create worker from external file
  createWorker(name: string, workerFile: string): Worker {
    const worker = new Worker(workerFile);
    this.workers.set(name, worker);
    return worker;
  }

  // Get worker by name
  getWorker(name: string): Worker | undefined {
    return this.workers.get(name);
  }

  // Terminate worker
  terminateWorker(name: string): void {
    const worker = this.workers.get(name);
    if (worker) {
      worker.terminate();
      this.workers.delete(name);
    }
  }

  // Terminate all workers
  terminateAllWorkers(): void {
    for (const [name, worker] of this.workers) {
      worker.terminate();
    }
    this.workers.clear();
  }
}

// 2. Worker Communication
class WorkerCommunication {
  private worker: Worker;

  constructor(worker: Worker) {
    this.worker = worker;
  }

  // Send message to worker
  postMessage(message: any, transfer?: Transferable[]): void {
    this.worker.postMessage(message, transfer);
  }

  // Set onmessage handler
  onMessage(handler: (message: MessageEvent) => void): void {
    this.worker.onmessage = handler;
  }

  // Set onerror handler
  onError(handler: (error: ErrorEvent) => void): void {
    this.worker.onerror = handler;
  }

  // Send message and wait for response
  async sendMessage(message: any): Promise<any> {
    return new Promise((resolve, reject) => {
      const handleMessage = (e: MessageEvent) => {
        this.worker.removeEventListener('message', handleMessage);
        resolve(e.data);
      };

      const handleError = (e: ErrorEvent) => {
        this.worker.removeEventListener('error', handleError);
        reject(e.error);
      };

      this.worker.addEventListener('message', handleMessage);
      this.worker.addEventListener('error', handleError);

      this.worker.postMessage(message);
    });
  }
}

// 3. Worker Task Executor
class WorkerTaskExecutor {
  private workerManager: WorkerManager;

  constructor() {
    this.workerManager = new WorkerManager();
  }

  // Execute computation in worker
  async executeComputation(input: any): Promise<any> {
    const workerCode = `
      self.onmessage = function(e) {
        const input = e.data;
        const result = performComputation(input);
        self.postMessage(result);
      };

      function performComputation(input) {
        // Perform computation here
        return { result: input.value * 2 };
      }
    `;

    const worker = this.workerManager.createInlineWorker('computation', workerCode);
    const comm = new WorkerCommunication(worker);

    const result = await comm.sendMessage(input);
    this.workerManager.terminateWorker('computation');

    return result;
  }

  // Execute parallel computations
  async executeParallel(inputs: any[], workerCode: string): Promise<any[]> {
    const workers: Worker[] = [];
    const promises: Promise<any>[] = [];

    for (const input of inputs) {
      const worker = this.workerManager.createInlineWorker(`worker-${inputs.indexOf(input)}`, workerCode);
      workers.push(worker);

      const comm = new WorkerCommunication(worker);
      promises.push(comm.sendMessage(input));
    }

    const results = await Promise.all(promises);

    // Clean up workers
    workers.forEach(worker => worker.terminate());

    return results;
  }
}

// 4. Worker Pool
class WorkerPool {
  private workers: Worker[] = [];
  private taskQueue: Array<{ task: any; resolve: (value: any) => void; reject: (reason: any) => void }> = [];
  private availableWorkers: Worker[] = [];
  private inFlightTasks: Map<Worker, { task: any; resolve: (value: any) => void; reject: (reason: any) => void }> = new Map();

  constructor(workerCode: string, poolSize: number) {
    // Create workers
    for (let i = 0; i < poolSize; i++) {
      const blob = new Blob([workerCode], { type: 'application/javascript' });
      const workerUrl = URL.createObjectURL(blob);
      const worker = new Worker(workerUrl);

      worker.onmessage = (e) => {
        const task = this.inFlightTasks.get(worker);
        if (task) {
          task.resolve(e.data);
          this.inFlightTasks.delete(worker);
          this.releaseWorker(worker);
        }
      };

      worker.onerror = (e) => {
        const task = this.inFlightTasks.get(worker);
        if (task) {
          task.reject(e.error);
          this.inFlightTasks.delete(worker);
          this.releaseWorker(worker);
        }
      };

      this.workers.push(worker);
      this.availableWorkers.push(worker);
    }
  }

  // Execute task
  async execute(task: any): Promise<any> {
    return new Promise((resolve, reject) => {
      this.taskQueue.push({ task, resolve, reject });
      this.processQueue();
    });
  }

  private processQueue(): void {
    if (this.taskQueue.length === 0 || this.availableWorkers.length === 0) {
      return;
    }

    const taskItem = this.taskQueue.shift();
    const worker = this.availableWorkers.shift()!;

    this.inFlightTasks.set(worker, taskItem);
    worker.postMessage(taskItem.task);
  }

  private releaseWorker(worker: Worker): void {
    this.availableWorkers.push(worker);
    this.processQueue();
  }

  // Terminate all workers
  terminate(): void {
    this.workers.forEach(worker => worker.terminate());
    this.workers = [];
    this.availableWorkers = [];
    this.taskQueue = [];
    this.inFlightTasks.clear();
  }
}

// 5. Shared Worker
class SharedWorkerManager {
  private sharedWorker: SharedWorker | null = null;

  // Create shared worker
  createSharedWorker(name: string, workerCode: string): SharedWorker {
    const blob = new Blob([workerCode], { type: 'application/javascript' });
    const workerUrl = URL.createObjectURL(blob);
    this.sharedWorker = new SharedWorker(workerUrl, name);
    return this.sharedWorker;
  }

  // Connect to shared worker port
  connect(): MessagePort {
    if (!this.sharedWorker) {
      throw new Error('Shared worker not created');
    }

    return this.sharedWorker.port;
  }

  // Start connection
  start(): void {
    const port = this.connect();
    port.start();
  }

  // Post message to shared worker
  postMessage(message: any): void {
    const port = this.connect();
    port.postMessage(message);
  }

  // Set message handler
  onMessage(handler: (message: MessageEvent) => void): void {
    const port = this.connect();
    port.onmessage = handler;
  }
}

// 6. Worker with Progress Tracking
class WorkerWithProgress {
  private worker: Worker;
  private communication: WorkerCommunication;

  constructor(workerCode: string) {
    const blob = new Blob([workerCode], { type: 'application/javascript' });
    const workerUrl = URL.createObjectURL(blob);
    this.worker = new Worker(workerUrl);
    this.communication = new WorkerCommunication(this.worker);
  }

  // Execute task with progress callback
  async executeWithProgress(
    task: any,
    onProgress: (progress: number) => void
  ): Promise<any> {
    return new Promise((resolve, reject) => {
      this.communication.onMessage = (e: MessageEvent) => {
        const data = e.data;

        if (data.type === 'progress') {
          onProgress(data.value);
        } else if (data.type === 'complete') {
          resolve(data.result);
        } else if (data.type === 'error') {
          reject(new Error(data.message));
        }
      };

      this.communication.onError = (e: ErrorEvent) => {
        reject(e.error);
      };

      this.communication.postMessage(task);
    });
  }

  // Terminate worker
  terminate(): void {
    this.worker.terminate();
  }
}

// 7. Batch Processing with Workers
class BatchWorkerProcessor {
  private workerManager = new WorkerManager();

  // Process batch of items
  async processBatch<T, R>(
    items: T[],
    processorCode: string,
    batchSize: number = 10,
    onProgress?: (current: number, total: number) => void
  ): Promise<R[]> {
    const results: R[] = [];
    const batches: T[][] = [];

    // Split into batches
    for (let i = 0; i < items.length; i += batchSize) {
      batches.push(items.slice(i, i + batchSize));
    }

    // Process each batch
    for (let i = 0; i < batches.length; i++) {
      const batch = batches[i];
      const batchResults = await this.processBatchImpl(batch, processorCode);
      results.push(...batchResults);

      if (onProgress) {
        onProgress(Math.min((i + 1) * batchSize, items.length), items.length);
      }
    }

    return results;
  }

  private async processBatchImpl<T, R>(batch: T[], processorCode: string): Promise<R[]> {
    const workerCode = `
      ${processorCode}

      self.onmessage = function(e) {
        const batch = e.data;
        const results = batch.map(processItem);
        self.postMessage(results);
      };
    `;

    const worker = this.workerManager.createInlineWorker('batch', workerCode);
    const comm = new WorkerCommunication(worker);

    const results = await comm.sendMessage(batch);
    this.workerManager.terminateWorker('batch');

    return results;
  }
}

// 8. Worker Utilities
class WorkerUtils {
  // Check if Web Workers are supported
  static isSupported(): boolean {
    return typeof Worker !== 'undefined';
  }

  // Check if Shared Workers are supported
  static isSharedWorkerSupported(): boolean {
    return typeof SharedWorker !== 'undefined';
  }

  // Create worker from function
  static createWorkerFromFunction(fn: Function): Worker {
    const fnString = fn.toString();
    const workerCode = `
      const workerFunction = ${fnString};
      self.onmessage = (e) => {
        const result = workerFunction(e.data);
        self.postMessage(result);
      };
    `;

    const blob = new Blob([workerCode], { type: 'application/javascript' });
    const workerUrl = URL.createObjectURL(blob);
    return new Worker(workerUrl);
  }

  // Execute function in worker
  static async executeInWorker<T, R>(fn: (input: T) => R, input: T): Promise<R> {
    const worker = this.createWorkerFromFunction(fn);

    return new Promise((resolve, reject) => {
      worker.onmessage = (e) => {
        resolve(e.data as R);
        worker.terminate();
      };

      worker.onerror = (e) => {
        reject(e.error);
        worker.terminate();
      };

      worker.postMessage(input);
    });
  }
}

// Usage Examples
async function demonstrateWebWorkers() {
  console.log('=== Web TypeScript Web Workers Examples ===\n');

  // Check support
  console.log('--- Web Workers Support ---');
  console.log(`Web Workers supported: ${WorkerUtils.isSupported()}`);
  console.log(`Shared Workers supported: ${WorkerUtils.isSharedWorkerSupported()}`);

  // 1. Basic worker
  console.log('\n--- 1. Basic Web Worker ---');
  const workerManager = new WorkerManager();

  const basicWorkerCode = `
    self.onmessage = function(e) {
      const data = e.data;
      console.log('Worker received:', data);
      const result = data.value * 2;
      self.postMessage({ result: result });
    };
  `;

  const worker = workerManager.createInlineWorker('basic', basicWorkerCode);
  const comm = new WorkerCommunication(worker);

  comm.onMessage = (e) => {
    console.log(`Worker response: ${JSON.stringify(e.data)}`);
  };

  comm.postMessage({ value: 21 });

  // Wait for response
  await new Promise(resolve => setTimeout(resolve, 100));
  workerManager.terminateWorker('basic');

  // 2. Execute computation in worker
  console.log('\n--- 2. Execute Computation ---');
  const executor = new WorkerTaskExecutor();

  const computationResult = await executor.executeComputation({ value: 10 });
  console.log(`Computation result: ${JSON.stringify(computationResult)}`);

  // 3. Parallel execution
  console.log('\n--- 3. Parallel Execution ---');
  const parallelWorkerCode = `
    self.onmessage = function(e) {
      const input = e.data;
      const result = input * input; // Square the input
      self.postMessage(result);
    };
  `;

  const inputs = [1, 2, 3, 4, 5];
  const parallelResults = await executor.executeParallel(inputs, parallelWorkerCode);
  console.log(`Parallel results: ${parallelResults.join(', ')}`);

  // 4. Worker with progress
  console.log('\n--- 4. Worker with Progress ---');
  const progressWorkerCode = `
    self.onmessage = function(e) {
      const task = e.data;

      // Simulate progress
      for (let i = 0; i <= 100; i += 10) {
        self.postMessage({ type: 'progress', value: i });
      }

      self.postMessage({ type: 'complete', result: task.input * 2 });
    };
  `;

  const progressWorker = new WorkerWithProgress(progressWorkerCode);
  const progressResult = await progressWorker.executeWithProgress(
    { input: 15 },
    (progress) => console.log(`Progress: ${progress}%`)
  );
  console.log(`Result with progress: ${progressResult.result}`);
  progressWorker.terminate();

  // 5. Batch processing
  console.log('\n--- 5. Batch Processing ---');
  const batchProcessor = new BatchWorkerProcessor();

  const processorCode = `
    function processItem(item) {
      return item * item;
    }
  `;

  const items = Array.from({ length: 25 }, (_, i) => i + 1);
  const batchResults = await batchProcessor.processBatch(
    items,
    processorCode,
    5,
    (current, total) => console.log(`Batch progress: ${current}/${total}`)
  );

  console.log(`Batch results (first 10): ${batchResults.slice(0, 10).join(', ')}...`);

  // 6. Execute function in worker
  console.log('\n--- 6. Execute Function in Worker ---');
  const squareResult = await WorkerUtils.executeInWorker(
    (x: number) => x * x,
    7
  );
  console.log(`Square result: ${squareResult}`);

  // 7. Heavy computation
  console.log('\n--- 7. Heavy Computation ---');
  const heavyWorkerCode = `
    self.onmessage = function(e) {
      const n = e.data.n;
      let sum = 0;

      for (let i = 1; i <= n; i++) {
        sum += i;
      }

      self.postMessage({ sum: sum });
    };
  `;

  const heavyWorker = workerManager.createInlineWorker('heavy', heavyWorkerCode);
  const heavyComm = new WorkerCommunication(heavyWorker);

  const heavyResult = await heavyComm.sendMessage({ n: 1000000 });
  console.log(`Heavy computation result: Sum from 1 to 1000000 = ${heavyResult.sum}`);

  workerManager.terminateWorker('heavy');

  console.log('\n=== All Web Workers Examples Completed ===');
}

// Export classes
export { WorkerManager, WorkerCommunication, WorkerTaskExecutor, WorkerPool, SharedWorkerManager, WorkerWithProgress, BatchWorkerProcessor, WorkerUtils };
export { demonstrateWebWorkers };
代码typescript中等

异步操作

掌握async/await模式、Promises和TypeScript中的并发执行

难度

5/10

预计时间

25 min

标签

typescript, web, multithreading, async

前置条件

Intermediate TypeScript, Async/Await

typescript
// Web TypeScript Async/Await Operations Examples
// Mastering Promises, async/await, and concurrent execution patterns

// 1. Promise Basics
class PromiseBasics {
  // Create a resolving promise
  static resolve<T>(value: T): Promise<T> {
    return Promise.resolve(value);
  }

  // Create a rejecting promise
  static reject<T>(error: T): Promise<never> {
    return Promise.reject(error);
  }

  // Create promise from callback
  static fromCallback<T>(
    callback: (cb: (error: Error | null, result: T) => void) => void
  ): Promise<T> {
    return new Promise((resolve, reject) => {
      callback((error, result) => {
        if (error) {
          reject(error);
        } else {
          resolve(result);
        }
      });
    });
  }

  // Delay execution
  static delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  // Timeout a promise
  static withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string = 'Timeout'): Promise<T> {
    return Promise.race([
      promise,
      PromiseBasics.delay(timeoutMs).then(() => {
        throw new Error(errorMessage);
      })
    ]);
  }

  // Retry promise
  static async retry<T>(
    fn: () => Promise<T>,
    maxAttempts: number = 3,
    delayMs: number = 1000
  ): Promise<T> {
    let lastError: Error;

    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        return await fn();
      } catch (error) {
        lastError = error as Error;
        if (attempt < maxAttempts) {
          await this.delay(delayMs * attempt);
        }
      }
    }

    throw lastError!;
  }
}

// 2. Async Control Flow
class AsyncControlFlow {
  // Execute sequentially
  static async sequential<T>(tasks: Array<() => Promise<T>>): Promise<T[]> {
    const results: T[] = [];

    for (const task of tasks) {
      const result = await task();
      results.push(result);
    }

    return results;
  }

  // Execute parallel with limit
  static async parallelWithLimit<T>(
    tasks: Array<() => Promise<T>>,
    limit: number
  ): Promise<T[]> {
    const results: T[] = [];
    const executing: Promise<void>[] = [];

    for (const task of tasks) {
      const promise = task().then(result => {
        results.push(result);
      });

      executing.push(promise);

      if (executing.length >= limit) {
        await Promise.race(executing);
        executing.splice(executing.findIndex(p => p === promise), 1);
      }
    }

    await Promise.all(executing);
    return results;
  }

  // Execute parallel with batching
  static async batchParallel<T>(
    items: T[],
    processor: (item: T) => Promise<any>,
    batchSize: number
  ): Promise<any[]> {
    const results: any[] = [];

    for (let i = 0; i < items.length; i += batchSize) {
      const batch = items.slice(i, i + batchSize);
      const batchResults = await Promise.all(batch.map(processor));
      results.push(...batchResults);
    }

    return results;
  }

  // Execute with fallback
  static async withFallback<T>(
    primary: () => Promise<T>,
    fallback: () => Promise<T>
  ): Promise<T> {
    try {
      return await primary();
    } catch {
      return await fallback();
    }
  }

  // Execute with circuit breaker
  static withCircuitBreaker<T>(
    fn: () => Promise<T>,
    options: {
      timeout?: number;
      maxFailures?: number;
      resetTimeout?: number;
    } = {}
  ): () => Promise<T> {
    let failures = 0;
    let lastFailureTime = 0;
    let circuitOpen = false;

    const {
      timeout = 5000,
      maxFailures = 5,
      resetTimeout = 60000
    } = options;

    return async () => {
      if (circuitOpen) {
        if (Date.now() - lastFailureTime > resetTimeout) {
          circuitOpen = false;
          failures = 0;
        } else {
          throw new Error('Circuit breaker is open');
        }
      }

      try {
        const result = await PromiseBasics.withTimeout(fn(), timeout);
        failures = 0;
        return result;
      } catch (error) {
        failures++;
        lastFailureTime = Date.now();

        if (failures >= maxFailures) {
          circuitOpen = true;
        }

        throw error;
      }
    };
  }
}

// 3. Async Utilities
class AsyncUtilities {
  // Map array asynchronously
  static async map<T, R>(
    array: T[],
    mapper: (item: T, index: number) => Promise<R>
  ): Promise<R[]> {
    const promises = array.map((item, index) => mapper(item, index));
    return Promise.all(promises);
  }

  // Filter array asynchronously
  static async filter<T>(
    array: T[],
    predicate: (item: T, index: number) => Promise<boolean>
  ): Promise<T[]> {
    const results = await Promise.all(
      array.map(async (item, index) => ({
        item,
        keep: await predicate(item, index)
      }))
    );

    return results.filter(result => result.keep).map(result => result.item);
  }

  // Reduce array asynchronously
  static async reduce<T, R>(
    array: T[],
    reducer: (accumulator: R, item: T, index: number) => Promise<R>,
    initialValue: R
  ): Promise<R> {
    let accumulator = initialValue;

    for (let i = 0; i < array.length; i++) {
      accumulator = await reducer(accumulator, array[i], i);
    }

    return accumulator;
  }

  // Find asynchronously
  static async find<T>(
    array: T[],
    predicate: (item: T) => Promise<boolean>
  ): Promise<T | undefined> {
    for (const item of array) {
      if (await predicate(item)) {
        return item;
      }
    }
    return undefined;
  }

  // Some asynchronously
  static async some<T>(
    array: T[],
    predicate: (item: T) => Promise<boolean>
  ): Promise<boolean> {
    for (const item of array) {
      if (await predicate(item)) {
        return true;
      }
    }
    return false;
  }

  // Every asynchronously
  static async every<T>(
    array: T[],
    predicate: (item: T) => Promise<boolean>
  ): Promise<boolean> {
    for (const item of array) {
      if (!(await predicate(item))) {
        return false;
      }
    }
    return true;
  }
}

// 4. Async Queue
class AsyncQueue<T> {
  private queue: T[] = [];
  private pendingWaiters: Array<(value: T) => void> = [];

  // Enqueue item
  enqueue(item: T): void {
    if (this.pendingWaiters.length > 0) {
      const waiter = this.pendingWaiters.shift()!;
      waiter(item);
    } else {
      this.queue.push(item);
    }
  }

  // Dequeue item
  async dequeue(): Promise<T> {
    if (this.queue.length > 0) {
      return this.queue.shift()!;
    }

    return new Promise(resolve => {
      this.pendingWaiters.push(resolve);
    });
  }

  // Get size
  get size(): number {
    return this.queue.length;
  }
}

// 5. Async Mutex
class AsyncMutex {
  private locked = false;
  private waiters: Array<() => void> = [];

  // Acquire lock
  async acquire(): Promise<void> {
    if (!this.locked) {
      this.locked = true;
      return;
    }

    return new Promise(resolve => {
      this.waiters.push(resolve);
    });
  }

  // Release lock
  release(): void {
    if (this.waiters.length > 0) {
      const waiter = this.waiters.shift()!;
      waiter();
    } else {
      this.locked = false;
    }
  }

  // Execute critical section
  async execute<T>(fn: () => Promise<T>): Promise<T> {
    await this.acquire();
    try {
      return await fn();
    } finally {
      this.release();
    }
  }
}

// 6. Async Semaphore
class AsyncSemaphore {
  private permits: number;
  private waiters: Array<() => void> = [];

  constructor(permits: number) {
    this.permits = permits;
  }

  // Acquire permit
  async acquire(): Promise<void> {
    if (this.permits > 0) {
      this.permits--;
      return;
    }

    return new Promise(resolve => {
      this.waiters.push(resolve);
    });
  }

  // Release permit
  release(): void {
    if (this.waiters.length > 0) {
      const waiter = this.waiters.shift()!;
      waiter();
    } else {
      this.permits++;
    }
  }

  // Execute with semaphore
  async execute<T>(fn: () => Promise<T>): Promise<T> {
    await this.acquire();
    try {
      return await fn();
    } finally {
      this.release();
    }
  }
}

// 7. Async Cache
class AsyncCache<K, V> {
  private cache = new Map<K, V>();
  private pending = new Map<K, Promise<V>>();

  // Get or compute value
  async getOrCompute(key: K, compute: () => Promise<V>): Promise<V> {
    // Check cache
    if (this.cache.has(key)) {
      return this.cache.get(key)!;
    }

    // Check pending computation
    if (this.pending.has(key)) {
      return this.pending.get(key)!;
    }

    // Compute new value
    const promise = compute().then(value => {
      this.cache.set(key, value);
      this.pending.delete(key);
      return value;
    });

    this.pending.set(key, promise);
    return promise;
  }

  // Get value
  get(key: K): V | undefined {
    return this.cache.get(key);
  }

  // Set value
  set(key: K, value: V): void {
    this.cache.set(key, value);
  }

  // Clear cache
  clear(): void {
    this.cache.clear();
    this.pending.clear();
  }

  // Get size
  get size(): number {
    return this.cache.size;
  }
}

// 8. Async Rate Limiter
class AsyncRateLimiter {
  private queue: Array<() => void> = [];
  private running = 0;
  private interval: number;

  constructor(concurrency: number, intervalMs: number) {
    this.interval = intervalMs;
    this.running = concurrency;

    // Start ticker
    setInterval(() => {
      if (this.queue.length > 0 && this.running < concurrency) {
        const task = this.queue.shift()!;
        task();
        this.running--;
      }
    }, intervalMs);
  }

  // Execute with rate limiting
  async execute<T>(fn: () => Promise<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      const task = async () => {
        try {
          const result = await fn();
          resolve(result);
        } catch (error) {
          reject(error);
        }
      };

      if (this.running > 0) {
        this.running--;
        task();
      } else {
        this.queue.push(task);
      }
    });
  }
}

// Usage Examples
async function demonstrateAsyncOperations() {
  console.log('=== Web TypeScript Async/Await Operations Examples ===\n');

  // 1. Promise basics
  console.log('--- 1. Promise Basics ---');
  const resolved = await PromiseBasics.resolve(42);
  console.log(`Resolved: ${resolved}`);

  try {
    await PromiseBasics.reject(new Error('Test error'));
  } catch (error) {
    console.log(`Rejected: ${(error as Error).message}`);
  }

  await PromiseBasics.delay(100);
  console.log('Delay completed');

  // 2. Sequential vs parallel
  console.log('\n--- 2. Sequential vs Parallel ---');

  const tasks = [
    () => PromiseBasics.delay(100).then(() => 1),
    () => PromiseBasics.delay(200).then(() => 2),
    () => PromiseBasics.delay(150).then(() => 3)
  ];

  const startTime = Date.now();
  const sequentialResults = await AsyncControlFlow.sequential(tasks);
  console.log(`Sequential: ${sequentialResults.join(', ')} (${Date.now() - startTime}ms)`);

  const parallelResults = await Promise.all(tasks.map(t => t()));
  console.log(`Parallel: ${parallelResults.join(', ')} (${Date.now() - startTime}ms)`);

  // 3. Parallel with limit
  console.log('\n--- 3. Parallel with Limit ---');
  const limitStartTime = Date.now();
  const limitedResults = await AsyncControlFlow.parallelWithLimit(tasks, 2);
  console.log(`Limited (2): ${limitedResults.join(', ')} (${Date.now() - limitStartTime}ms)`);

  // 4. Async map
  console.log('\n--- 4. Async Map ---');
  const numbers = [1, 2, 3, 4, 5];
  const doubled = await AsyncUtilities.map(numbers, async (n) => {
    await PromiseBasics.delay(50);
    return n * 2;
  });
  console.log(`Doubled: ${doubled.join(', ')}`);

  // 5. Async filter
  console.log('\n--- 5. Async Filter ---');
  const evens = await AsyncUtilities.filter(numbers, async (n) => {
    await PromiseBasics.delay(10);
    return n % 2 === 0;
  });
  console.log(`Even numbers: ${evens.join(', ')}`);

  // 6. Async queue
  console.log('\n--- 6. Async Queue ---');
  const queue = new AsyncQueue<number>();

  queue.enqueue(1);
  queue.enqueue(2);
  queue.enqueue(3);

  console.log(`Queue size: ${queue.size}`);
  console.log(`Dequeue: ${await queue.dequeue()}`);
  console.log(`Dequeue: ${await queue.dequeue()}`);

  // 7. Async mutex
  console.log('\n--- 7. Async Mutex ---');
  const mutex = new AsyncMutex();

  const mutexTask = mutex.execute(async () => {
    console.log('Critical section start');
    await PromiseBasics.delay(100);
    console.log('Critical section end');
    return 'done';
  });

  console.log(`Mutex result: ${await mutexTask}`);

  // 8. Async cache
  console.log('\n--- 8. Async Cache ---');
  const cache = new AsyncCache<string, string>();

  const computeResult1 = await cache.getOrCompute('key1', async () => {
    console.log('Computing value for key1');
    await PromiseBasics.delay(100);
    return 'value1';
  });

  const computeResult2 = await cache.getOrCompute('key1', async () => {
    console.log('This should not print');
    return 'value1-different';
  });

  console.log(`Cache results: ${computeResult1}, ${computeResult2}`);
  console.log(`Cache size: ${cache.size}`);

  // 9. Retry
  console.log('\n--- 9. Retry ---');
  let attempts = 0;
  const retryResult = await PromiseBasics.retry(async () => {
    attempts++;
    console.log(`Attempt ${attempts}`);
    if (attempts < 3) {
      throw new Error('Not yet');
    }
    return 'success';
  }, 5, 50);

  console.log(`Retry result: ${retryResult}`);

  // 10. Timeout
  console.log('\n--- 10. Timeout ---');
  try {
    await PromiseBasics.withTimeout(
      PromiseBasics.delay(2000).then(() => 'slow'),
      100,
      'Too slow'
    );
  } catch (error) {
    console.log(`Timeout error: ${(error as Error).message}`);
  }

  console.log('\n=== All Async/Await Examples Completed ===');
}

// Export classes
export { PromiseBasics, AsyncControlFlow, AsyncUtilities, AsyncQueue, AsyncMutex, AsyncSemaphore, AsyncCache, AsyncRateLimiter };
export { demonstrateAsyncOperations };
代码typescript复杂

同步原语

使用Atomics、SharedArrayBuffer和锁实现同步

难度

8/10

预计时间

40 min

标签

typescript, web, multithreading, synchronization

前置条件

Advanced TypeScript, Atomics API, SharedArrayBuffer

typescript
// Web TypeScript Synchronization Primitives Examples
// Using Atomics, SharedArrayBuffer, and custom synchronization

// 1. Atomics Operations
class AtomicsOperations {
  // Create shared buffer
  static createSharedBuffer(size: number): Int32Array {
    const buffer = new SharedArrayBuffer(size * Int32Array.BYTES_PER_ELEMENT);
    return new Int32Array(buffer);
  }

  // Compare and swap
  static compareAndSwap(
    array: Int32Array,
    index: number,
    expectedValue: number,
    newValue: number
  ): boolean {
    return Atomics.compareExchange(array, index, expectedValue, newValue) === expectedValue;
  }

  // Add atomically
  static add(array: Int32Array, index: number, value: number): number {
    return Atomics.add(array, index, value);
  }

  // Sub atomically
  static sub(array: Int32Array, index: number, value: number): number {
    return Atomics.sub(array, index, value);
  }

  // Increment atomically
  static increment(array: Int32Array, index: number): number {
    return Atomics.add(array, index, 1);
  }

  // Decrement atomically
  static decrement(array: Int32Array, index: number): number {
    return Atomics.sub(array, index, 1);
  }

  // Load atomically
  static load(array: Int32Array, index: number): number {
    return Atomics.load(array, index);
  }

  // Store atomically
  static store(array: Int32Array, index: number, value: number): void {
    Atomics.store(array, index, value);
  }

  // Wait for notification
  static waitAsync(array: Int32Array, index: number, expectedValue: number, timeout?: number): Promise<'ok' | 'not-equal' | 'timed-out'> {
    return Atomics.waitAsync(array, index, expectedValue, timeout).then(() => 'ok');
  }

  // Notify waiters
  static notify(array: Int32Array, index: number, count: number): number {
    return Atomics.notify(array, index, count);
  }
}

// 2. Spinlock
class Spinlock {
  private locked: Int32Array;

  constructor() {
    this.locked = AtomicsOperations.createSharedBuffer(1);
  }

  // Acquire lock (busy-wait)
  acquire(): void {
    while (true) {
      // Try to acquire lock
      const previous = AtomicsOperations.exchange(this.locked, 0, 1);

      if (previous === 0) {
        // Lock acquired
        return;
      }

      // Wait for notification
      Atomics.wait(this.locked, 0, 1);
    }
  }

  // Release lock
  release(): void {
    AtomicsOperations.store(this.locked, 0, 0);
    AtomicsOperations.notify(this.locked, 0, 1);
  }
}

// 3. Mutex (Better than Spinlock)
class Mutex {
  private locked: Int32Array;

  constructor() {
    this.locked = AtomicsOperations.createSharedBuffer(1);
  }

  // Acquire lock with timeout
  async acquire(timeoutMs: number = 5000): Promise<boolean> {
    const start = Date.now();

    while (true) {
      // Try to acquire lock
      const previous = AtomicsOperations.compareAndSwap(this.locked, 0, 0, 1);

      if (previous === 0) {
        return true;
      }

      // Check timeout
      if (Date.now() - start > timeoutMs) {
        return false;
      }

      // Wait with timeout
      await AtomicsOperations.waitAsync(this.locked, 0, 1, 100);
    }
  }

  // Release lock
  release(): void {
    AtomicsOperations.store(this.locked, 0, 0);
    AtomicsOperations.notify(this.locked, 0, 1);
  }

  // Execute critical section
  async execute<T>(fn: () => Promise<T>, timeoutMs?: number): Promise<T> {
    const acquired = await this.acquire(timeoutMs);

    if (!acquired) {
      throw new Error('Mutex acquisition timeout');
    }

    try {
      return await fn();
    } finally {
      this.release();
    }
  }
}

// 4. Semaphore
class Semaphore {
  private permits: Int32Array;

  constructor(initialPermits: number) {
    this.permits = AtomicsOperations.createSharedBuffer(1);
    AtomicsOperations.store(this.permits, 0, initialPermits);
  }

  // Acquire permit
  async acquire(timeoutMs: number = 5000): Promise<boolean> {
    const start = Date.now();

    while (true) {
      const current = AtomicsOperations.load(this.permits, 0);

      if (current > 0) {
        // Try to acquire permit
        const previous = AtomicsOperations.compareAndSwap(
          this.permits,
          0,
          current,
          current - 1
        );

        if (previous === current) {
          return true;
        }
      }

      // Check timeout
      if (Date.now() - start > timeoutMs) {
        return false;
      }

      // Wait
      await AtomicsOperations.waitAsync(this.permits, 0, current, 100);
    }
  }

  // Release permit
  release(): void {
    AtomicsOperations.increment(this.permits, 0);
    AtomicsOperations.notify(this.permits, 0, 1);
  }

  // Execute with semaphore
  async execute<T>(fn: () => Promise<T>): Promise<T> {
    await this.acquire();
    try {
      return await fn();
    } finally {
      this.release();
    }
  }
}

// 5. Barrier
class Barrier {
  private count: Int32Array;
  private waiting: Int32Array;
  private total: number;

  constructor(parties: number) {
    this.total = parties;
    this.count = AtomicsOperations.createSharedBuffer(1);
    this.waiting = AtomicsOperations.createSharedBuffer(1);
  }

  // Wait for all parties
  async wait(): Promise<void> {
    const index = AtomicsOperations.add(this.waiting, 0, 1);

    if (index === this.total) {
      // Last party resets the barrier
      AtomicsOperations.store(this.waiting, 0, 0);
      AtomicsOperations.store(this.count, 0, 0);
      AtomicsOperations.notify(this.count, 0, this.total);
    } else {
      // Wait for last party
      await AtomicsOperations.waitAsync(this.count, 0, 0);
    }
  }

  // Reset barrier
  reset(): void {
    AtomicsOperations.store(this.waiting, 0, 0);
    AtomicsOperations.store(this.count, 0, 0);
  }
}

// 6. Read-Write Lock
class ReadWriteLock {
  private readers: Int32Array;
  private writer: Int32Array;

  constructor() {
    this.readers = AtomicsOperations.createSharedBuffer(1);
    this.writer = AtomicsOperations.createSharedBuffer(1);
  }

  // Acquire read lock
  async acquireReadLock(): Promise<void> {
    while (true) {
      // Wait if writer is active
      while (AtomicsOperations.load(this.writer, 0) !== 0) {
        await AtomicsOperations.waitAsync(this.writer, 0, 0);
      }

      // Increment readers
      AtomicsOperations.increment(this.readers, 0);

      // Check if writer is still not active
      if (AtomicsOperations.load(this.writer, 0) === 0) {
        return;
      }

      // Writer became active, back off
      AtomicsOperations.decrement(this.readers, 0);
    }
  }

  // Release read lock
  releaseReadLock(): void {
    AtomicsOperations.decrement(this.readers, 0);

    // Notify potential writer if no readers left
    if (AtomicsOperations.load(this.readers, 0) === 0) {
      AtomicsOperations.notify(this.writer, 0, 1);
    }
  }

  // Acquire write lock
  async acquireWriteLock(): Promise<void> {
    // Mark writer as waiting
    while (true) {
      // Wait for readers to finish
      while (AtomicsOperations.load(this.readers, 0) !== 0) {
        await AtomicsOperations.waitAsync(this.readers, 0, 1);
      }

      // Try to acquire write lock
      const previous = AtomicsOperations.compareAndSwap(this.writer, 0, 0, 1);

      if (previous === 0) {
        return;
      }
    }
  }

  // Release write lock
  releaseWriteLock(): void {
    AtomicsOperations.store(this.writer, 0, 0);
    AtomicsOperations.notify(this.writer, 0, 1);
    AtomicsOperations.notify(this.readers, 0, 1);
  }

  // Execute with read lock
  async executeRead<T>(fn: () => Promise<T>): Promise<T> {
    await this.acquireReadLock();
    try {
      return await fn();
    } finally {
      this.releaseReadLock();
    }
  }

  // Execute with write lock
  async executeWrite<T>(fn: () => Promise<T>): Promise<T> {
    await this.acquireWriteLock();
    try {
      return await fn();
    } finally {
      this.releaseWriteLock();
    }
  }
}

// 7. Concurrent Counter
class ConcurrentCounter {
  private counter: Int32Array;

  constructor(initialValue: number = 0) {
    this.counter = AtomicsOperations.createSharedBuffer(1);
    AtomicsOperations.store(this.counter, 0, initialValue);
  }

  // Increment and get
  incrementAndGet(): number {
    return AtomicsOperations.add(this.counter, 0, 1) + 1;
  }

  // Get and increment
  getAndIncrement(): number {
    return AtomicsOperations.add(this.counter, 0, 1);
  }

  // Decrement and get
  decrementAndGet(): number {
    return AtomicsOperations.sub(this.counter, 0, 1) - 1;
  }

  // Get and decrement
  getAndDecrement(): number {
    return AtomicsOperations.sub(this.counter, 0, 1);
  }

  // Get current value
  get(): number {
    return AtomicsOperations.load(this.counter, 0);
  }

  // Set value
  set(value: number): void {
    AtomicsOperations.store(this.counter, 0, value);
  }

  // Add and get
  addAndGet(value: number): number {
    return AtomicsOperations.add(this.counter, 0, value) + value;
  }
}

// 8. Producer-Consumer Queue
class ProducerConsumerQueue<T> {
  private buffer: T[] = [];
  private size: Int32Array;
  private count: Int32Array;
  private head: Int32Array;
  private tail: Int32Array;

  constructor(capacity: number) {
    this.buffer = new Array(capacity);
    this.size = AtomicsOperations.createSharedBuffer(1);
    this.count = AtomicsOperations.createSharedBuffer(1);
    this.head = AtomicsOperations.createSharedBuffer(1);
    this.tail = AtomicsOperations.createSharedBuffer(1);

    AtomicsOperations.store(this.size, 0, capacity);
  }

  // Enqueue item
  async enqueue(item: T): Promise<void> {
    while (true) {
      const currentCount = AtomicsOperations.load(this.count, 0);
      const capacity = AtomicsOperations.load(this.size, 0);

      if (currentCount < capacity) {
        // Not full, enqueue
        const tail = AtomicsOperations.load(this.tail, 0);
        this.buffer[tail] = item;
        AtomicsOperations.store(this.tail, 0, (tail + 1) % capacity);
        AtomicsOperations.increment(this.count, 0);
        AtomicsOperations.notify(this.count, 0, 1);
        return;
      }

      // Full, wait for space
      await AtomicsOperations.waitAsync(this.count, 0, currentCount);
    }
  }

  // Dequeue item
  async dequeue(): Promise<T> {
    while (true) {
      const currentCount = AtomicsOperations.load(this.count, 0);

      if (currentCount > 0) {
        // Not empty, dequeue
        const head = AtomicsOperations.load(this.head, 0);
        const capacity = AtomicsOperations.load(this.size, 0);
        const item = this.buffer[head];

        this.buffer[head] = undefined as any;
        AtomicsOperations.store(this.head, 0, (head + 1) % capacity);
        AtomicsOperations.decrement(this.count, 0);
        AtomicsOperations.notify(this.count, 0, 1);
        return item;
      }

      // Empty, wait for item
      await AtomicsOperations.waitAsync(this.count, 0, currentCount);
    }
  }

  // Get current count
  get count(): number {
    return AtomicsOperations.load(this.count, 0);
  }
}

// Usage Examples
async function demonstrateSynchronization() {
  console.log('=== Web TypeScript Synchronization Primitives Examples ===\n');

  // 1. Atomics operations
  console.log('--- 1. Atomics Operations ---');
  const buffer = AtomicsOperations.createSharedBuffer(5);

  for (let i = 0; i < buffer.length; i++) {
    AtomicsOperations.store(buffer, i, i * 10);
  }

  console.log('Buffer values:');
  for (let i = 0; i < buffer.length; i++) {
    console.log(`  [${i}] = ${buffer[i]}`);
  }

  AtomicsOperations.add(buffer, 0, 5);
  console.log(`After add to [0]: ${buffer[0]}`);

  // 2. Concurrent counter
  console.log('\n--- 2. Concurrent Counter ---');
  const counter = new ConcurrentCounter(0);

  // Simulate concurrent increments
  const incrementTasks = Array.from({ length: 10 }, (_, i) =>
    PromiseBasics.delay(Math.random() * 100).then(() => {
      counter.incrementAndGet();
    })
  );

  await Promise.all(incrementTasks);
  console.log(`Final counter value: ${counter.get()}`);

  // 3. Mutex
  console.log('\n--- 3. Mutex ---');
  const mutex = new Mutex();
  let sharedResource = 0;

  const mutexTasks = Array.from({ length: 5 }, (_, i) =>
    mutex.execute(async () => {
      const value = sharedResource;
      console.log(`Task ${i} read: ${value}`);
      await PromiseBasics.delay(50);
      sharedResource = value + 1;
      console.log(`Task ${i} wrote: ${sharedResource}`);
      return sharedResource;
    })
  );

  await Promise.all(mutexTasks);
  console.log(`Final shared resource value: ${sharedResource}`);

  // 4. Semaphore
  console.log('\n--- 4. Semaphore ---');
  const semaphore = new Semaphore(2); // Allow 2 concurrent operations

  let activeCount = 0;
  let maxActive = 0;

  const semaphoreTasks = Array.from({ length: 10 }, (_, i) =>
    semaphore.execute(async () => {
      activeCount++;
      maxActive = Math.max(maxActive, activeCount);
      console.log(`Task ${i} started (active: ${activeCount})`);
      await PromiseBasics.delay(Math.random() * 200);
      activeCount--;
      console.log(`Task ${i} completed`);
    })
  );

  await Promise.all(semaphoreTasks);
  console.log(`Max concurrent tasks: ${maxActive}`);

  // 5. Barrier
  console.log('\n--- 5. Barrier ---');
  const barrier = new Barrier(3);

  const barrierTasks = Array.from({ length: 3 }, (_, i) =>
    barrier.wait().then(() => {
      console.log(`Task ${i} passed barrier`);
    })
  );

  await Promise.all(barrierTasks);

  // 6. Producer-Consumer
  console.log('\n--- 6. Producer-Consumer Queue ---');
  const queue = new ProducerConsumerQueue<number>(5);

  // Producer
  queue.enqueue(1);
  setTimeout(() => queue.enqueue(2), 100);
  setTimeout(() => queue.enqueue(3), 200);

  // Consumer
  const item1 = await queue.dequeue();
  console.log(`Dequeued: ${item1}`);

  const item2 = await queue.dequeue();
  console.log(`Dequeued: ${item2}`);

  console.log(`Queue count: ${queue.count}`);

  console.log('\n=== All Synchronization Primitives Examples Completed ===');
}

// Import PromiseBasics
class PromiseBasics {
  static delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Export classes
export { AtomicsOperations, Spinlock, Mutex, Semaphore, Barrier, ReadWriteLock, ConcurrentCounter, ProducerConsumerQueue };
export { demonstrateSynchronization };

工具

经常与该案例搭配使用的工具

相关内容

相关案例集合

工具使用指南

帮助搜索与理解工作流的案例说明

标题

Web TypeScript 多线程编程示例

描述

Web TypeScript 多线程编程示例,包括Web Workers、异步操作和并行处理

概览

Web TypeScript 多线程编程示例,包括Web Workers、异步操作和并行处理

适用场景

  • Use this sample set when you want reference inputs for Web TypeScript 多线程编程示例.
  • Use it to preview output formats and compare related sample variants.

使用方式

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

常见用途

  • Web Workers
  • 异步操作
  • 同步原语

常见问题

What is included in Web TypeScript 多线程编程示例?

This page includes curated sample entries, related tools, and neighboring sample collections for Web TypeScript 多线程编程示例.

首页
工具3197
案例593
可视化461
文件查看器103
专题229
标签333
图像、音频与视频655

图像、音频、视频处理、转换与优化工具

数学、日期与金融644

计算器、数值计算、日期逻辑、统计与金融工具

设计与颜色296

颜色、版式、图形、视觉样式与设计辅助工具

文本与写作209

写作、清洗、格式化、提取与文本分析工具

开发与 Web193

开发者工具、网络处理、Web 调试与自动化辅助工具

转换与编码175

格式、文件、压缩包、单位与编码转换工具

界面截图结构化、人工校对与开发交付
钢琴旋律草稿创作、MIDI 核验与试听样稿交付
复古游戏纹理制作、候选评审与素材交付
操作截图到可复核图文指南与培训交付
网页改版响应式视觉回归审核与证据交付

© 2026 Elysia Tools. 保留所有权利。

文档价格关于我们服务条款隐私政策Cookie 政策联系我们

Development

JSON 转 TypeScript

将 JSON 数据转换为 TypeScript interface 或 type,支持联合类型、可选字段与嵌套对象推断

Web & Internet

Web 搜索(SearXNG JSON)

通过 s.stdlang.com 的 SearXNG 实例搜索网页,返回 JSON 结果供自动化或后续工具使用。

Development

OpenAPI 转 TypeScript 类型生成器

将 OpenAPI 或 Swagger 的 JSON/YAML 规范转换为 TypeScript 接口类型、请求参数类型和响应类型,并支持输出格式与命名风格配置

Media

Chrome网上应用商店截图调整

将图片调整为Chrome网上应用商店截图尺寸,同时保留完整内容和原始宽高比例

Format Conversion

Web Push RFC 8030 请求 + VAPID + RFC 8291 负载加密编码器

编码完整的 Web Push 发送流程:RFC 8291 aes128gcm 负载加密、RFC 8292 VAPID ES256 JWT、RFC 8030 头部、APNs/FCM 头部对照与解密往返验证。

Design

网页字体配对实验室

并排预览 标题 + 正文 的 Google 字体配对,调节字重与行高,复制即可粘贴的 CSS @import + 变量代码。精选 22 款字体及 7 组经典搭配预设。

Media

批量图片修剪

同时修剪多张图片,使用多种修剪方法进行批处理和ZIP输出

Health

血型计算器

根据遗传学计算父母和孩子的可能血型

Rust

Web Rust 多线程编程示例

Web Rust 多线程编程示例,包括线程创建、同步和线程池

TypeScript

Web TypeScript 加密安全示例

Web TypeScript 加密安全示例,包括哈希计算、对称加密和Base64编码

TypeScript

Web TypeScript 数据库操作示例

Web TypeScript 数据库操作示例,包括SQLite连接、SQL查询执行和事务处理

TypeScript

Web TypeScript 数据结构示例

Web TypeScript 数据结构示例,包括数组操作、哈希表和链表

TypeScript

Web TypeScript 日期时间示例

Web TypeScript 日期和时间示例,包括获取当前时间、格式化、解析和操作

TypeScript

Web TypeScript 桌面端功能示例

Web TypeScript 桌面端功能示例,包括文件对话框、消息框和系统托盘