# All files / src errorId.ts

54.9% Statements 28/51
35% Branches 7/20
50% Functions 4/8
55.1% Lines 27/49

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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    1071x

    1x

    1x

    9x
    9x

    4x
    4x

    5x
    5x

    9x
    9x
    3x

    6x
    2x

    4x

    6x

    1x
    16x

    1x
    10x

    9x
    9x
    9x
    468x
    468x
    468x

    9x

     import { ERRORTYPES, EVENTTYPES } from './common/common'
    import { ReportDataType } from './types/transportData'
    const allErrorNumber: unknown = {}
    /**
     * error合并规则
     * @param data
     */
    export default function createErrorId(data: ReportDataType): number | null {
      let id: any
      const originUrl = getRealPageOrigin(data.url)
      switch (data.type) {
        case ERRORTYPES.FETCH_ERROR:
          id = data.type + data.request.method + data.response.status + getRealPath(data.request.url) + originUrl
          break
        case ERRORTYPES.JAVASCRIPT_ERROR:
        case ERRORTYPES.VUE_ERROR:
        case ERRORTYPES.REACT_ERROR:
          id = data.type + data.name + data.message + originUrl
          break
        case ERRORTYPES.BUSINESS_ERROR:
        case ERRORTYPES.LOG_ERROR:
          id = data.customTag + data.type + data.name + originUrl
          break
        case ERRORTYPES.PROMISE_ERROR:
          id = generatePromiseErrorId(data, originUrl)
          break
        default:
          id = data.type + data.message + originUrl
          break
      }
      id = hashCode(id)
      if (allErrorNumber[id] > 1) {
        return null
      }
      if (typeof allErrorNumber[id] === 'number') {
        allErrorNumber[id]++
      } else {
        allErrorNumber[id] = 1
      }

      return id
    }

    function generatePromiseErrorId(data: ReportDataType, originUrl: string) {
      const locationUrl = getRealPath(data.url)
      if (data.name === EVENTTYPES.UNHANDLEDREJECTION) {
        return data.type + objectOrder(data.message) + originUrl
      }
      return data.type + data.name + objectOrder(data.message) + locationUrl
    }

    /**
     * 排序对象键值对
     * ../param reason promise.reject
     */
    function objectOrder(reason: any) {
      const sortFn = (obj: any) => {
        return Object.keys(obj)
          .sort()
          .reduce((total, key) => {
            if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
              total[key] = sortFn(obj[key])
            } else {
              total[key] = obj[key]
            }
            return total
          }, {})
      }
      try {
        if (/\{.*\}/.test(reason)) {
          let obj = JSON.parse(reason)
          obj = sortFn(obj)
          return JSON.stringify(obj)
        }
      } catch (error) {
        return reason
      }
    }

    /**
     * http://.../project?id=1#a => http://.../project
     * http://.../id/123=> http://.../id/{param}
     *
     * @param url
     */
    export function getRealPath(url: string): string {
      return url.replace(/[\?#].*$/, '').replace(/\/\d+([\/]*$)/, '{param}$1')
    }
    /**
     * http://a.b.com/#/project?id=1 => a.b.com
     * @param url
     */
    export function getRealPageOrigin(url: string): string {
      return getRealPath(url.replace(/(\S+)(\/#\/)(\S*)/, `$1`).replace(/(\S*)(\/\/)(\S+)/, '$3'))
    }

    function hashCode(str: string): number {
      let hash = 0
      Iif (str.length == 0) return hash
      for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i)
        hash = (hash << 5) - hash + char
        hash = hash & hash
      }
      return hash
    }