{"id":22845229,"url":"https://github.com/qquanwei/trackpoint-tools","last_synced_at":"2025-04-05T01:08:43.245Z","repository":{"id":40744541,"uuid":"98177045","full_name":"Qquanwei/trackpoint-tools","owner":"Qquanwei","description":"Javascript 无痕埋点辅助工具库(React,Vue)，track everywhere,","archived":false,"fork":false,"pushed_at":"2023-03-08T03:23:16.000Z","size":627,"stargazers_count":369,"open_issues_count":7,"forks_count":64,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-04-25T00:02:38.569Z","etag":null,"topics":["bury","javascript","react","track","trackpoint","vue"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Qquanwei.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-24T10:05:49.000Z","updated_at":"2024-04-14T14:32:13.000Z","dependencies_parsed_at":"2024-12-13T03:16:25.351Z","dependency_job_id":"18bad532-c09f-4b4c-9d79-497a3fa072ec","html_url":"https://github.com/Qquanwei/trackpoint-tools","commit_stats":{"total_commits":47,"total_committers":4,"mean_commits":11.75,"dds":"0.17021276595744683","last_synced_commit":"1cf9f677c99cb2e29946b9277200d290a8df5a3d"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Qquanwei%2Ftrackpoint-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Qquanwei%2Ftrackpoint-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Qquanwei%2Ftrackpoint-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Qquanwei%2Ftrackpoint-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Qquanwei","download_url":"https://codeload.github.com/Qquanwei/trackpoint-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247271532,"owners_count":20911587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bury","javascript","react","track","trackpoint","vue"],"created_at":"2024-12-13T03:16:22.209Z","updated_at":"2025-04-05T01:08:43.205Z","avatar_url":"https://github.com/Qquanwei.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"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)\n[![npm](https://img.shields.io/npm/v/trackpoint-tools.svg)](https://www.npmjs.com/package/trackpoint-tools)\n\n\n# 不能再让埋点继续侵入我们的逻辑了，我们需要做点什么\n\n## trackpoint-tools\n\n埋点逻辑往往是侵入性的，我们需要将这块代码拆分出去。\n幸运的是es6,es7 给我们提供了可能。\n\n```\nnpm i trackpoint-tools --save\n```\n\n使用trackpoint-tools你可能会用下面的方式写埋点信息, 完全不侵入原有逻辑\n\n```\nclass SomeComponent {\n  @track(composeWith(ms =\u003e (element) =\u003e ajax.post(url, {ms, name: element.name}), time))\n  onClick (element) {\n    return element.someMethod()\n  }\n}\n```\n\n示例(React 全): https://codesandbox.io/s/wqxr0j2qj5\n示例(Vue 演示):https://codesandbox.io/s/oxxw580yz5\n## API 列表\n\n* [before](#before)\n* [after](#after)\n* [once](#once)\n* [track](#track)\n* [nop](#nop)\n* [composeWith](#composeWith)\n* [evolve](#evolve)\n* [time](#time)\n* [identity](#identity)\n* [createCounter](#createCounter)\n\n\n所有的API都满足curryable, 所有的trackFn 都不会影响正常逻辑执行。\n\ntrackFn 指实际执行逻辑的跟踪函数， fn为普通的业务函数。\n\n### \u003ca name=\"before\"\u003e\u003c/a\u003e before(trackFn, fn)\n\n```\nimport { before } from 'trackpoint-tools'\n\nclass SomeComponent {\n    onClick = before((name) =\u003e console.log('seed some ', name))((name) =\u003e {\n       // normal\n       console.log('normal click ', name)\n    })\n}\n```\n\nonClick('me')\n\n-\u003e\n\n```\n  seed some me\n  normal click me\n```\n\n### \u003ca name=\"after\"\u003e\u003c/a\u003eafter(trackFn, fn)\n\n```\nimport { after } from 'trackpoint-tools'\n\nclass SomeComponent {\n  onClick = after(() =\u003e console.log('send after'))(() =\u003e {\n    // normal\n    console.log('normal click')\n  })\n}\n```\n\nonClick\n\n-\u003e\n\n```\n    normal click\n    send after\n\n```\n\n\nUsing Promise\n\n```\nimport { after } from 'trackpoint-tools'\n\nclass SomeComponent {\n    onClick = after(() =\u003e console.log('send after'))(() =\u003e {\n         return ajax.post(...).then(() =\u003e {\n             console.log('normal click')\n         })\n    })\n}\n```\n\nonClick\n\n-\u003e\n\n```\n    normal click\n    send after\n\n```\n\n### \u003ca name=\"once\"\u003e\u003c/a\u003eonce(fn)\n\nsame as lodash/once\n[lodash/once](https://lodash.com/docs/4.17.4#once)\n\n\n### \u003ca name=\"track\"\u003e\u003c/a\u003etrack(fn)\n\n借助es7的decorator提案可以让我们以一种非常优雅的方式使用高阶函数， track用来将普通的class函数包装成decorator\n使用起来非常简单\n\nbabel plugin: https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy\n\n```\nclass SomeComponent {\n  @track(before(() =\u003e console.log('before')))\n  onClick () {\n    console.log('click')\n  }\n\n  @track(after(() =\u003e console.log('after')))\n  onClickAjax () {\n    return ajax.get(...').then(() =\u003e {\n        console.log('request done')\n    })\n  }\n}\n```\n\n-\u003e\n\n```\n before\n click\n```\n\n-\u003e\n\n```\n request done\n after\n```\n\n### \u003ca name=\"nop\"\u003e\u003c/a\u003e nop()\n\ndo nothing , empty function\n\n### \u003ca name=\"composeWith\"\u003e\u003c/a\u003e composeWith(convergeFn, [ops])\n\ncomposeWith 类似after, 主要执行收集执行期间性能的操作, 并将参数传给普通trackFn更高一阶函数\n\nops会被展开为 `fn -\u003e (...args) -\u003e {}`, 执行顺序为从右到左，如果只有一项操作\n可省略数组直接传入ops函数\n\n\n```\nclass SomeComponent {\n  @track(composeWith(m =\u003e (...args) =\u003e console.log(m + 'ms'), [time]))\n  onClick () {\n     ...\n     ...\n     return 0\n  }\n}\n```\n\n-\u003e\n\n```\n somecomponent.onClick() // return 0 . output 100ms\n\n```\n\n### \u003ca name=\"evolve\"\u003e\u003c/a\u003e evolve(evols)\n\nevols是一个求值对象，value为实际求值操作(例如time, identity).\n与composeWith结合使用.\n\n注意，evolve中每个操作都有可能跟踪fn，但是fn只能执行一次，所以只有fn第一次执行才能进行有效的性能计算。\n所以需要将性能计算写在evols的第一行(但其实顺序并不能保障 [ref](https://github.com/lodash/lodash/blob/npm/mapValues.js#L27))。\n\n例如\n\n```\nconst evols = {\n  timeMs: trackpoint.time,\n  value: trackpoint.identity\n}\n\nconst trackFn = ({timeMs, value}) =\u003e (...args) =\u003e {\n  console.log('timeMs ', timeMs)\n  console.log('value ', value)\n}\n\nconst evolve = trackpoint.evolve\n\nclass SomeComponent {\n  @track(composeWith(trackFn, evolve(evols)))\n  onClick() {\n    // some sync operation, about 300ms\n    return 101\n  }\n}\n```\n\noutput-\u003e\n\n```\ntimeMs 301\nvalue 101\n```\n\n### \u003ca name=\"time\"\u003e\u003c/a\u003e time(fn) -\u003e (...) -\u003e ms\n\n测量普通函数与thenable函数执行时间, 单位毫秒\n\n```\n time(() =\u003e console.log('out'))() // return 1\n```\n\n### \u003ca name=\"identity\"\u003e\u003c/a\u003e identity(fn) -\u003e (...) -\u003e value\n\n输出fn的执行结果\n\n### \u003ca name=\"createCounter\"\u003e\u003c/a\u003e createCounter() -\u003e (fn) -\u003e (...) -\u003e value\n\n创建一个计数器，可以用来统计fn函数被调用的次数\n\n```\nconst trackFn = ({count}) =\u003e (...args) =\u003e console.log('count is:', count)\nconst fn = () =\u003e { console.log('why always click me?')}\n\n\nconst composeFn = composeWith(trackFn, evolve({count: createCounter()}))(fn)\n\ncomposeFn()\n// why always click me?\n// count is 1\ncomposeFn()\n// why always click me?\n// count is 2\n...\n...\n```\n\n## 关于 this\n\n使用\n```\nclass SomeComponent {\n  @track(before(function () {\n  }))\n  onClick () {\n  }\n}\n```\n会自动将this绑定到before的函数体中。\n\n注意： JS中此处如果有箭头函数会绑定到全局的this(null), 所以在此处不建议使用箭头函数\n\n## TL;DR\n\n推荐使用es7的decorator\n大量流程控制虽然为高阶函数, 但实际调用的参数皆为用户输入的参数\n\n## 贡献\n\n欢迎fork, 有新的想法可以直接提PR\n\n* build\n\n`npm run build`\n\n* test\n\n`npm run test`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqquanwei%2Ftrackpoint-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqquanwei%2Ftrackpoint-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqquanwei%2Ftrackpoint-tools/lists"}