Skip to content

⬅️ Back to Table of Contents

📄 useWebWorkerFn

📊 Analysis Summary

Metric Count
🔧 Functions 5
📦 Imports 6
⚡ Async/Await Patterns 3
📐 Interfaces 2
📑 Type Aliases 1

📚 Table of Contents

🛠️ File Location:

📂 packages/core/useWebWorkerFn/index.ts

📦 Imports

Name Source
ShallowRef vue
ConfigurableWindow ../_configurable
tryOnScopeDispose @vueuse/shared
shallowRef vue
defaultWindow ../_configurable
createWorkerBlobUrl ./lib/createWorkerBlobUrl

Async/Await Patterns

Type Function Await Expressions Promise Chains
promise-chain useWebWorkerFn none new Promise(...), Promise.reject
promise-chain callWorker none new Promise(...)
promise-chain workerFn none Promise.reject

Functions

useWebWorkerFn(fn: T, options: UseWebWorkerOptions): UseWebWorkerFnReturn<T>

Run expensive function without blocking the UI, using a simple syntax that makes use of Promise.

Parameters:

  • fn any: No description
  • options any: No description

See: https://vueuse.org/useWebWorkerFn

Raw JSDoc
/**
 * Run expensive function without blocking the UI, using a simple syntax that makes use of Promise.
 *
 * @see https://vueuse.org/useWebWorkerFn
 * @param fn
 * @param options
 */

Calls:

  • shallowRef (from vue)
  • worker.terminate
  • URL.revokeObjectURL
  • window.clearTimeout
  • workerTerminate
  • tryOnScopeDispose (from @vueuse/shared)
  • createWorkerBlobUrl (from ./lib/createWorkerBlobUrl)
  • resolve
  • reject
  • e.preventDefault
  • setTimeout
  • worker?.postMessage
  • console.error
  • Promise.reject
  • generateWorker
  • callWorker

Internal Comments:

/* eslint-disable-next-line prefer-promise-reject-errors */

Code
export function useWebWorkerFn<T extends (...fnArgs: any[]) => any>(fn: T, options: UseWebWorkerOptions = {}): UseWebWorkerFnReturn<T> {
  const {
    dependencies = [],
    localDependencies = [],
    timeout,
    window = defaultWindow,
  } = options

  let worker: (Worker & { _url?: string }) | undefined
  const workerStatus = shallowRef<WebWorkerStatus>('PENDING')
  const promise = shallowRef<({ reject?: (result: ReturnType<T> | ErrorEvent) => void, resolve?: (result: ReturnType<T>) => void })>({})
  const timeoutId = shallowRef<number>()

  const workerTerminate = (status: WebWorkerStatus = 'PENDING') => {
    if (worker && worker._url && window) {
      worker.terminate()
      URL.revokeObjectURL(worker._url)
      promise.value = {}
      worker = undefined
      window.clearTimeout(timeoutId.value)
      workerStatus.value = status
    }
  }

  workerTerminate()

  tryOnScopeDispose(workerTerminate)

  const generateWorker = () => {
    const blobUrl = createWorkerBlobUrl(fn, dependencies, localDependencies)
    const newWorker: Worker & { _url?: string } = new Worker(blobUrl)
    newWorker._url = blobUrl

    newWorker.onmessage = (e: MessageEvent) => {
      const { resolve = () => { }, reject = () => { } } = promise.value
      const [status, result] = e.data as [WebWorkerStatus, ReturnType<T>]

      switch (status) {
        case 'SUCCESS':
          resolve(result)
          workerTerminate(status)
          break
        default:
          reject(result)
          workerTerminate('ERROR')
          break
      }
    }

    newWorker.onerror = (e: ErrorEvent) => {
      const { reject = () => { } } = promise.value
      e.preventDefault()
      reject(e)
      workerTerminate('ERROR')
    }

    if (timeout) {
      timeoutId.value = setTimeout(workerTerminate, timeout, 'TIMEOUT_EXPIRED') as any
    }
    return newWorker
  }

  const callWorker = (...fnArgs: Parameters<T>) => new Promise<ReturnType<T>>((resolve, reject) => {
    promise.value = {
      resolve,
      reject,
    }
    worker?.postMessage([[...fnArgs]])

    workerStatus.value = 'RUNNING'
  })

  const workerFn = (...fnArgs: Parameters<T>) => {
    if (workerStatus.value === 'RUNNING') {
      console.error(
        '[useWebWorkerFn] You can only run one instance of the worker at a time.',
      )
      /* eslint-disable-next-line prefer-promise-reject-errors */
      return Promise.reject()
    }

    worker = generateWorker()
    return callWorker(...fnArgs)
  }

  return {
    workerFn,
    workerStatus,
    workerTerminate,
  }
}

Internal helpers

Declared inside another function in this file.

workerTerminate(status: WebWorkerStatus): void

Parameters:

  • status WebWorkerStatus

Returns: void

Calls:

  • worker.terminate
  • URL.revokeObjectURL
  • window.clearTimeout
Code
(status: WebWorkerStatus = 'PENDING') => {
    if (worker && worker._url && window) {
      worker.terminate()
      URL.revokeObjectURL(worker._url)
      promise.value = {}
      worker = undefined
      window.clearTimeout(timeoutId.value)
      workerStatus.value = status
    }
  }

generateWorker(): Worker & { _url?: string; }

Returns: Worker & { _url?: string; }

Calls:

  • createWorkerBlobUrl (from ./lib/createWorkerBlobUrl)
  • resolve
  • workerTerminate
  • reject
  • e.preventDefault
  • setTimeout
Code
() => {
    const blobUrl = createWorkerBlobUrl(fn, dependencies, localDependencies)
    const newWorker: Worker & { _url?: string } = new Worker(blobUrl)
    newWorker._url = blobUrl

    newWorker.onmessage = (e: MessageEvent) => {
      const { resolve = () => { }, reject = () => { } } = promise.value
      const [status, result] = e.data as [WebWorkerStatus, ReturnType<T>]

      switch (status) {
        case 'SUCCESS':
          resolve(result)
          workerTerminate(status)
          break
        default:
          reject(result)
          workerTerminate('ERROR')
          break
      }
    }

    newWorker.onerror = (e: ErrorEvent) => {
      const { reject = () => { } } = promise.value
      e.preventDefault()
      reject(e)
      workerTerminate('ERROR')
    }

    if (timeout) {
      timeoutId.value = setTimeout(workerTerminate, timeout, 'TIMEOUT_EXPIRED') as any
    }
    return newWorker
  }

callWorker(fnArgs: Parameters<T>): Promise<ReturnType<T>>

Parameters:

  • fnArgs Parameters<T>

Returns: Promise<ReturnType<T>>

Code
(...fnArgs: Parameters<T>) => new Promise<ReturnType<T>>((resolve, reject) => {
    promise.value = {
      resolve,
      reject,
    }
    worker?.postMessage([[...fnArgs]])

    workerStatus.value = 'RUNNING'
  })

workerFn(fnArgs: Parameters<T>): Promise<ReturnType<T>>

Parameters:

  • fnArgs Parameters<T>

Returns: Promise<ReturnType<T>>

Calls:

  • console.error
  • Promise.reject
  • generateWorker
  • callWorker

Internal Comments:

/* eslint-disable-next-line prefer-promise-reject-errors */

Code
(...fnArgs: Parameters<T>) => {
    if (workerStatus.value === 'RUNNING') {
      console.error(
        '[useWebWorkerFn] You can only run one instance of the worker at a time.',
      )
      /* eslint-disable-next-line prefer-promise-reject-errors */
      return Promise.reject()
    }

    worker = generateWorker()
    return callWorker(...fnArgs)
  }

Interfaces

UseWebWorkerOptions

Interface Code
export interface UseWebWorkerOptions extends ConfigurableWindow {
  /**
   * Number of milliseconds before killing the worker
   *
   * @default undefined
   */
  timeout?: number
  /**
   * An array that contains the external dependencies needed to run the worker
   */
  dependencies?: string[]
  /**
   * An array that contains the local dependencies needed to run the worker
   */
  localDependencies?: Function[]
}

Properties

Name Type Optional Description
timeout number not shown
dependencies string[] not shown
localDependencies Function[] not shown

UseWebWorkerFnReturn<T extends (...fnArgs: any[]) => any>

Interface Code
export interface UseWebWorkerFnReturn<T extends (...fnArgs: any[]) => any> {
  workerFn: (...fnArgs: Parameters<T>) => Promise<ReturnType<T>>
  workerStatus: ShallowRef<WebWorkerStatus>
  workerTerminate: (status?: WebWorkerStatus) => void
}

Properties

Name Type Optional Description
workerFn (...fnArgs: Parameters<T>) => Promise<ReturnType<T>> not shown
workerStatus ShallowRef<WebWorkerStatus> not shown
workerTerminate (status?: WebWorkerStatus) => void not shown

Type Aliases

WebWorkerStatus

type WebWorkerStatus = | 'PENDING'
    | 'SUCCESS'
    | 'RUNNING'
    | 'ERROR'
    | 'TIMEOUT_EXPIRED';

Generated by Syntax Scribe