UNPKG

tsp-component

Version:

提供多端和react版本的UI组件

224 lines (215 loc) 6.47 kB
/// <reference path="./definition.d.ts" /> import WebApi from '../ajax/webapi'; import { userAgent } from '../util/device'; import { urlStartIndexForString, getCurrentRoute } from '../util/router'; declare const process: { env: { NODE_ENV: string; } }; class Exception { /** * api名称 */ public static apiname: string = '/api/product/exception/create'; /** * 产品编码 */ public static productCode: ExceptionProductCode; /** * 经度 */ public static lat: string; /** * 纬度 */ public static lng: string; /** * 账号 */ public static account: string; /** * 微信用户标示 */ public static openId: string; /** * 版本 */ public static version: string; /** * 网络环境 */ public static network: string; /** * 接口请求类 */ public static webapi: WebApi; /** * 发送错误 */ public static send(data: ExceptionSendParams): void { if (process.env.NODE_ENV !== 'production' || !Exception.productCode) { if (Exception.productCode) { console.log('异常上报的内容:'); console.log(data); } return; } const params: ExceptionData = { col: data.col, errorType: data.errorType || 1, line: data.line, content: data.content, details: data.details, productCode: data.productCode || Exception.productCode, url: data.url, userAgent, lat: Exception.lat, lng: Exception.lng, account: Exception.account, openId: Exception.openId, version: Exception.version, currentPage: getCurrentRoute(), network: Exception.network }; this.webapi.post({ api: Exception.apiname, type: 'post', contentType: 'application/json', timeoutStr: 'none', params, success: () => null, isCache: false }); } /** * 解析catch的错误 */ public static catchParse(e: Error): ExceptionData { const details = e.stack.trim(); let startIndex = urlStartIndexForString(details); let suffixIndex = details.indexOf('.js:') + 4; let lineEndIndex = details.substr(suffixIndex).indexOf(':') + suffixIndex; let endIndex = lineEndIndex + 6; let path = details.substr(startIndex, endIndex - startIndex); if (urlStartIndexForString(path, true) !== startIndex) { startIndex = urlStartIndexForString(path, true); path = path.substr(startIndex, endIndex - startIndex); startIndex = 0; suffixIndex = path.indexOf('.js:') + 4; lineEndIndex = path.substr(suffixIndex).indexOf(':') + suffixIndex; endIndex = lineEndIndex + 6; } const url = path.substr(startIndex, suffixIndex - startIndex - 1); const line = path.substr(suffixIndex, lineEndIndex - suffixIndex); const col = path.substr(lineEndIndex, endIndex - suffixIndex).replace(/[^0-9]/ig, ''); return { col: parseInt(col), line: parseInt(line), url, details: e.stack, content: `name: ${e.name}; message: ${e.message};`, errorType: 1, userAgent, lat: Exception.lat, lng: Exception.lng, account: Exception.account, openId: Exception.openId, version: Exception.version, currentPage: getCurrentRoute(), network: Exception.network }; } /** * catch时发送错误 */ public static catchSend(e: Error): void { const data: ExceptionSendParams = Exception.catchParse(e); if (process.env.NODE_ENV !== 'production') { console.log('异常解析结果:'); console.log(data); throw e; } else { Exception.send(data); } } /** * 监听异常 */ public static listen(): void { window.onerror = (msg: string, url: string, line: number, col: number, error: Error): boolean => { //没有URL不上报!上报也不知道错误 if (msg !== 'Script error.' && !url) { return true; } //采用异步的方式 //我遇到过在window.onunload进行ajax的堵塞上报 //由于客户端强制关闭webview导致这次堵塞上报有Network Error //我猜测这里window.onerror的执行流在关闭前是必然执行的 //而离开文章之后的上报对于业务来说是可丢失的 //所以我把这里的执行流放到异步事件去执行 //脚本的异常数降低了10倍 setTimeout(function(): void { const data: ExceptionData = { productCode: Exception.productCode, errorType: 1, col: 0, line: 0, url: '', content: '', details: '', userAgent, lat: Exception.lat, lng: Exception.lng, account: Exception.account, openId: Exception.openId, version: Exception.version, currentPage: getCurrentRoute(), network: Exception.network }; //不一定所有浏览器都支持col参数 col = col || (window.event && window.event['errorCharacter']) || 0; data.url = url; data.line = line; data.col = col; if (!!error && !!error.stack) { //如果浏览器有堆栈信息 //直接使用 data.content = `name: ${error.name}; message: ${error.message};`; data.details = error.stack; } else if (!!arguments.callee) { //尝试通过callee拿堆栈信息 let ext: any = []; let f = arguments.callee.caller; let c = 3; //这里只拿三层堆栈信息 while (f && (--c > 0)) { ext.push(f.toString()); if (f === f.caller) { //如果有环 break; } f = f.caller; } ext = ext.join(','); data.content = ext; } //把data上报到后台! if (process.env.NODE_ENV !== 'production') { console.log('onerror扑捉到的错误:'); console.log(data); } else { Exception.send(data); } }, 0); if (process.env.NODE_ENV !== 'production') { throw error; } else { return true; } }; } } export default Exception;