# All files / src/core errorId.ts

76.19% Statements 48/63
60.87% Branches 14/23
81.82% Functions 9/11
77.05% Lines 47/61

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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    1426x
    6x
    6x

    6x

    6x

    13x

    5x
    5x

    6x
    6x

    2x
    2x

    13x
    13x
    3x

    10x
    2x

    8x

    10x

    2x
    2x
    1x

    1x

    2x

    2x
    2x

    6x
    18x

    6x

    2x

    6x

    3x

    6x
    2x
    2x
    1x

    1x

    1x

    6x
    3x

    13x
    13x
    13x
    510x
    510x
    510x

    13x

     import { isWxMiniEnv, variableTypeDetection } from '@/utils'
    import { getAppId } from '@/wx-mini/constant'
    import { ERRORTYPES, EVENTTYPES } from '../common/constant'
    import { ReportDataType } from '../types/transportData'
    const allErrorNumber: unknown = {}
    /**
     * generate error unique Id
     * @param data
     */
    export default function createErrorId(data: ReportDataType, apikey: string): number | null {
      let id: any
      switch (data.type) {
        case ERRORTYPES.FETCH_ERROR:
          id = data.type + data.request.method + data.response.status + getRealPath(data.request.url) + apikey
          break
        case ERRORTYPES.JAVASCRIPT_ERROR:
        case ERRORTYPES.VUE_ERROR:
        case ERRORTYPES.REACT_ERROR:
          id = data.type + data.name + data.message + apikey
          break
        case ERRORTYPES.LOG_ERROR:
          id = data.customTag + data.type + data.name + apikey
          break
        case ERRORTYPES.PROMISE_ERROR:
          id = generatePromiseErrorId(data, apikey)
          break
        default:
          id = data.type + data.message + apikey
          break
      }
      id = hashCode(id)
      if (allErrorNumber[id] > 1) {
        return null
      }
      if (typeof allErrorNumber[id] === 'number') {
        allErrorNumber[id]++
      } else {
        allErrorNumber[id] = 1
      }

      return id
    }
    /**
     * 如果是UNHANDLEDREJECTION，则按照项目主域名来生成
     * 如果是其他的，按照当前页面来生成
     * @param data
     * @param originUrl
     */
    function generatePromiseErrorId(data: ReportDataType, apikey: string) {
      const locationUrl = getRealPath(data.url)
      if (data.name === EVENTTYPES.UNHANDLEDREJECTION) {
        return data.type + objectOrder(data.message) + apikey
      }
      return data.type + data.name + objectOrder(data.message) + locationUrl
    }

    /**
     * sort object keys
     * ../param reason promise.reject
     */
    function objectOrder(reason: any) {
      const sortFn = (obj: any) => {
        return Object.keys(obj)
          .sort()
          .reduce((total, key) => {
            if (variableTypeDetection.isObject(obj[key])) {
              total[key] = sortFn(obj[key])
            } else {
              total[key] = obj[key]
            }
            return total
          }, {})
      }
      try {
        Iif (/\{.*\}/.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')
    }

    /**
     *
     * @param url
     */
    export function getFlutterRealOrigin(url: string): string {
      // for apple
      return removeHashPath(getFlutterRealPath(url))
    }

    /**
     * 获取flutter的原始地址：每个用户的文件夹hash不同
     * @param url
     */
    export function getFlutterRealPath(url: string): string {
      // for apple
      return url.replace(/(\S+)(\/Documents\/)(\S*)/, `$3`)
    }
    /**
     * http://a.b.com/#/project?id=1 => a.b.com
     * wx => appId
     * @param url
     */
    export function getRealPageOrigin(url: string): string {
      const fileStartReg = /^file:\/\//
      if (fileStartReg.test(url)) {
        return getFlutterRealOrigin(url)
      }
      Iif (isWxMiniEnv) {
        return getAppId()
      }
      return getRealPath(removeHashPath(url).replace(/(\S*)(\/\/)(\S+)/, '$3'))
    }

    export function removeHashPath(url: string): string {
      return url.replace(/(\S+)(\/#\/)(\S*)/, `$1`)
    }

    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
    }