All files / utils signal.ts

82.86% Statements 29/35
75% Branches 9/12
85.71% Functions 6/7
84.85% Lines 28/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67                      2x     2x   2x 2x   2x 3x 3x 3x 2x 2x   3x 3x     2x 1x 1x         1x 1x     2x 5x 1x   4x 1x   3x 3x     3x     3x 3x       2x            
export interface SignalResult<T> {
  set(value: T): void
  throw(error: any): void
  get(): Promise<T>
}
 
/**
 * 信号。
 */
export function signal<T>(): SignalResult<T> {
  let value!: T
  let isOk = false
 
  let error!: any
  let isFail = false
 
  const $resolve: any[] = []
  const $reject: any[] = []
 
  const setValue: SignalResult<T>['set'] = _value => {
    value = _value
    if ($resolve.length) {
      $resolve.forEach(resolve => resolve(value))
      $resolve.length = 0
      $reject.length = 0
    }
    isOk = true
    isFail = false
  }
 
  const throwError: SignalResult<T>['throw'] = _error => {
    error = _error
    Iif ($reject.length) {
      $reject.forEach(reject => reject(error))
      $resolve.length = 0
      $reject.length = 0
    }
    isOk = false
    isFail = true
  }
 
  const getValue: SignalResult<T>['get'] = () => {
    if (isOk) {
      return Promise.resolve<T>(value)
    }
    if (isFail) {
      return Promise.reject(error)
    }
    return new Promise<T>((resolve, reject) => {
      Iif (isOk) {
        return resolve(value)
      }
      Iif (isFail) {
        return reject(error)
      }
      $resolve.push(resolve)
      $reject.push(reject)
    })
  }
 
  return {
    set: setValue,
    get: getValue,
    throw: throwError,
  }
}