Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/qquanwei/trackpoint-tools
Javascript 无痕埋点辅助工具库(React,Vue),track everywhere,
https://github.com/qquanwei/trackpoint-tools
bury javascript react track trackpoint vue
Last synced: 7 days ago
JSON representation
Javascript 无痕埋点辅助工具库(React,Vue),track everywhere,
- Host: GitHub
- URL: https://github.com/qquanwei/trackpoint-tools
- Owner: Qquanwei
- Created: 2017-07-24T10:05:49.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-03-08T03:23:16.000Z (almost 2 years ago)
- Last Synced: 2024-04-25T00:02:38.569Z (8 months ago)
- Topics: bury, javascript, react, track, trackpoint, vue
- Language: JavaScript
- Homepage:
- Size: 612 KB
- Stars: 369
- Watchers: 14
- Forks: 64
- Open Issues: 7
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
[![Node.js CI](https://github.com/Qquanwei/trackpoint-tools/actions/workflows/node.js.yml/badge.svg)](https://github.com/Qquanwei/trackpoint-tools/actions/workflows/node.js.yml)
[![npm](https://img.shields.io/npm/v/trackpoint-tools.svg)](https://www.npmjs.com/package/trackpoint-tools)# 不能再让埋点继续侵入我们的逻辑了,我们需要做点什么
## trackpoint-tools
埋点逻辑往往是侵入性的,我们需要将这块代码拆分出去。
幸运的是es6,es7 给我们提供了可能。```
npm i trackpoint-tools --save
```使用trackpoint-tools你可能会用下面的方式写埋点信息, 完全不侵入原有逻辑
```
class SomeComponent {
@track(composeWith(ms => (element) => ajax.post(url, {ms, name: element.name}), time))
onClick (element) {
return element.someMethod()
}
}
```示例(React 全): https://codesandbox.io/s/wqxr0j2qj5
示例(Vue 演示):https://codesandbox.io/s/oxxw580yz5
## API 列表* [before](#before)
* [after](#after)
* [once](#once)
* [track](#track)
* [nop](#nop)
* [composeWith](#composeWith)
* [evolve](#evolve)
* [time](#time)
* [identity](#identity)
* [createCounter](#createCounter)所有的API都满足curryable, 所有的trackFn 都不会影响正常逻辑执行。
trackFn 指实际执行逻辑的跟踪函数, fn为普通的业务函数。
```
import { before } from 'trackpoint-tools'class SomeComponent {
onClick = before((name) => console.log('seed some ', name))((name) => {
// normal
console.log('normal click ', name)
})
}
```onClick('me')
->
```
seed some me
normal click me
``````
import { after } from 'trackpoint-tools'class SomeComponent {
onClick = after(() => console.log('send after'))(() => {
// normal
console.log('normal click')
})
}
```onClick
->
```
normal click
send after```
Using Promise
```
import { after } from 'trackpoint-tools'class SomeComponent {
onClick = after(() => console.log('send after'))(() => {
return ajax.post(...).then(() => {
console.log('normal click')
})
})
}
```onClick
->
```
normal click
send after```
same as lodash/once
[lodash/once](https://lodash.com/docs/4.17.4#once)借助es7的decorator提案可以让我们以一种非常优雅的方式使用高阶函数, track用来将普通的class函数包装成decorator
使用起来非常简单babel plugin: https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy
```
class SomeComponent {
@track(before(() => console.log('before')))
onClick () {
console.log('click')
}@track(after(() => console.log('after')))
onClickAjax () {
return ajax.get(...').then(() => {
console.log('request done')
})
}
}
```->
```
before
click
```->
```
request done
after
```do nothing , empty function
### composeWith(convergeFn, [ops])
composeWith 类似after, 主要执行收集执行期间性能的操作, 并将参数传给普通trackFn更高一阶函数
ops会被展开为 `fn -> (...args) -> {}`, 执行顺序为从右到左,如果只有一项操作
可省略数组直接传入ops函数```
class SomeComponent {
@track(composeWith(m => (...args) => console.log(m + 'ms'), [time]))
onClick () {
...
...
return 0
}
}
```->
```
somecomponent.onClick() // return 0 . output 100ms```
evols是一个求值对象,value为实际求值操作(例如time, identity).
与composeWith结合使用.注意,evolve中每个操作都有可能跟踪fn,但是fn只能执行一次,所以只有fn第一次执行才能进行有效的性能计算。
所以需要将性能计算写在evols的第一行(但其实顺序并不能保障 [ref](https://github.com/lodash/lodash/blob/npm/mapValues.js#L27))。例如
```
const evols = {
timeMs: trackpoint.time,
value: trackpoint.identity
}const trackFn = ({timeMs, value}) => (...args) => {
console.log('timeMs ', timeMs)
console.log('value ', value)
}const evolve = trackpoint.evolve
class SomeComponent {
@track(composeWith(trackFn, evolve(evols)))
onClick() {
// some sync operation, about 300ms
return 101
}
}
```output->
```
timeMs 301
value 101
```测量普通函数与thenable函数执行时间, 单位毫秒
```
time(() => console.log('out'))() // return 1
```### identity(fn) -> (...) -> value
输出fn的执行结果
### createCounter() -> (fn) -> (...) -> value
创建一个计数器,可以用来统计fn函数被调用的次数
```
const trackFn = ({count}) => (...args) => console.log('count is:', count)
const fn = () => { console.log('why always click me?')}const composeFn = composeWith(trackFn, evolve({count: createCounter()}))(fn)
composeFn()
// why always click me?
// count is 1
composeFn()
// why always click me?
// count is 2
...
...
```## 关于 this
使用
```
class SomeComponent {
@track(before(function () {
}))
onClick () {
}
}
```
会自动将this绑定到before的函数体中。注意: JS中此处如果有箭头函数会绑定到全局的this(null), 所以在此处不建议使用箭头函数
## TL;DR
推荐使用es7的decorator
大量流程控制虽然为高阶函数, 但实际调用的参数皆为用户输入的参数## 贡献
欢迎fork, 有新的想法可以直接提PR
* build
`npm run build`
* test
`npm run test`