feat: catch error

This commit is contained in:
EnixCoda 2018-08-05 16:32:31 +08:00
parent 081be4ff4d
commit f707b393fc
4 changed files with 54 additions and 14 deletions

26
src/analytics.js Normal file
View file

@ -0,0 +1,26 @@
const LOG_ENDPOINT = ''
export function raiseError(error) {
return reportError(error)
}
export function withErrorLog(func) {
return function () {
try {
func()
} catch (error) {
raiseError(error)
}
}
}
function encodeParams(params) {
return Object.keys(params).map(key => `${key}=${encodeURIComponent(JSON.stringify(params[key]))}`).join('&')
}
function reportError(error) {
return fetch(`${LOG_ENDPOINT}?${encodeParams({
error: error && error.message || error,
path: window.location.href,
})}`)
}

View file

@ -4,8 +4,15 @@ import SideBar from './SideBar'
import { Gitako as GitakoCore } from '../driver/core'
import connect from '../driver/connect'
import { raiseError } from '../analytics'
@connect(GitakoCore)
export default class Gitako extends React.PureComponent {
componentDidCatch(error) {
raiseError(error)
}
render() {
return (
<SideBar />

View file

@ -1,18 +1,19 @@
import React from 'react'
import { withErrorLog } from "../analytics"
function async(func) {
return new Promise(resolve => setTimeout(() => resolve(func())))
}
function sync(func) {
return func()
}
function link(instance, sources) {
const wrappedMethods = {/* sources[key] -> wrappedMethods.method */}
const wrappedMethods = {/* [keyof sources] -> wrappedMethods.method */}
const map = new Map(/* sources.creator -> wrappedMethods.method */)
function dispatch(...args) {
if (Object.values(sources).includes(args[0])) {
map.get(args[0])(...args.slice(1))
} else {
setTimeout(
instance.setState.bind(instance, ...args),
)
}
}
Object.entries(sources).forEach(([key, createMethod]) => {
const method = createMethod(dispatch)
@ -20,6 +21,15 @@ function link(instance, sources) {
map.set(createMethod, method)
})
function dispatch(...args) {
const isFromSource = Object.values(sources).includes(args[0])
if (isFromSource) {
sync(withErrorLog(() => map.get(args[0])(...args.slice(1))))
} else {
async(() => instance.setState(...args))
}
}
return wrappedMethods
}
@ -32,9 +42,7 @@ export default function connect(mapping) {
boundCore = link(this, mapping)
render() {
return (
<ComponentClass {...this.props} {...this.boundCore} {...this.state}/>
)
return <ComponentClass {...this.props} {...this.boundCore} {...this.state} />
}
}
}

View file

@ -36,7 +36,6 @@ const init = dispatch => async () => {
})
dispatch(setShouldShow, errorDueToAuth)
} else {
console.error(err)
dispatch(setShouldShow, false)
}
}