工程结构
├── build
│ ├── outputs // 最终打包文件
│ └── temp // 暂存目录主要用于处理 es6 翻译后的文件
├── demo
│ └── index.html // 测试用的Demo
├── gulpfile.js
├── lib
│ ├── api
│ │ └── AnalyticsApi.js // SDK对外接口
│ ├── control // 包含基础的流程操作
│ │ ├── AnalyContext.js
│ │ └── InitializeHelper.js
│ ├── model // 上报的数据结构
│ │ ├── AnalyEvent.js
│ │ ├── PageInfo.js
│ │ └── UserInfo.js
│ ├── request // 包含所有的请求操作
│ │ ├── AnalyRequestRunnable.js
│ │ ├── AsyncPool.js
│ │ ├── DebugRequestRunnable.js
│ │ └── SinglePool.js
│ └── support // 工具方法
│ ├── AlBase64.js
│ ├── AlConsole.js
│ ├── AlCookie.js
│ ├── AlDevice.js
│ ├── AlMd5.js
│ ├── AlType.js
│ └── pool
│ ├── AlPool.js
│ ├── AlPoolRunnable.js
│ └── Serializable.js
└── package.json
项目解析
1. api
包含所有的对外接口,基本原则如下
- 不包含任何逻辑代码
- 简约明了
import AnalyContext from "../control/AnalyContext"
class Facade {
initialize(opts) {
AnalyContext.getInstance().initialize(opts);
}
....
}
//包含一个这个方法,是无奈之举,防止被外部代码bind
function buildMethods() {
const facade = new Facade();
return {
initialize: facade.initialize.bind(facade),
login: facade.login.bind(facade),
logout: facade.logout.bind(facade),
track: facade.track.bind(facade),
trackSinglePage: facade.trackSinglePage.bind(facade)
}
}
window.webAanlytics2020 = buildMethods();
control
包含初始化时的配置动作,比如配置参数校验,初始化监听动作
class AnalyContext {
// 持有整个应用期间需要长期使用的model
constructor() {
this.userInfo = new UserInfo();
this.pageInfo = new PageInfo();
}
initialize(opts) {
// 形式如下InitializeHelper帮助解析参数,后续代码开始配置
// 缺陷:逻辑部分应该放在, InitializeHelper中处理,但是代码不多,权衡下,放在AnalyContext容易改动
this.initializeHelper = new InitializeHelper();
this.initializeHelper.initialize(opts);
//debug 配置
if (this.initializeHelper.showLogEnable()) {
AlConsole.debug(true);
}
.....
}
}
model
这个层就更加简单了,全都是数据结构
class AnalyEvent {
constructor() {
this.event = "";
this.properties = {};
this.env = {}
}
.....
}
class UserInfo {
....
}
class PageInfo {
....
}
request
用于处理异步批量发送 或者 立即发送模式(Single Mode), 次部分的设计使用的是support目录下的pool功能,设计如下:
// 只包含一个run方法,支持序列话操作,用于支持日志本地存储
class AlPoolRunnable extends Serializable {
run() {};
}
// 该类是SingleMode模式和BatchMode模式的父类,用于处理不同模式的发送
class AlPool {
constructor() {}
run() {};
clean() {};
queueTo(runnable) {};
}
序列化
用于日志本地存储,避免日志丢失,每次序列化后,存储在window.localStorage
class Serializable {
readObject() {
return "";
}
writeObject(str) {
}
}
加密策略
==sorry 不能开放,可以根据具体情况在request请求或者在存储中做加密处理==
总结
- 保持模块独立性
- 不要局限设计,根据具体需求变更或简化设计