Files
huangguo_landpage/src/utils/eventTracker.ts
T
2026-09-15 16:25:45 +07:00

80 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 事件上报服务
*
* LandingSDK 由 index.html 异步加载,加载完成前 window.tracker 只是一个排队用的桩函数;
* v2 SDK 不再接受桩队列回放出来的泛型调用 track({ event })(会判「非法上报」丢弃),
* 所以这里等 SDK 就绪后再走具名方法 landingPageView / landingPageClick。
*/
import type { EventCode } from './types'
const SDK_READY_TIMEOUT_MS = 10000
const SDK_POLL_MS = 30
type LandingTracker = ((payload: Record<string, any>) => Promise<unknown>) & {
landingPageView?: (properties?: Record<string, any>) => Promise<unknown>
landingPageClick?: (properties?: Record<string, any>) => Promise<unknown>
}
// 等到 window.tracker 被 App.vue initTracker 替换成真正的 SDK track(带具名方法)为止。
// 注意:SDK 的 track 是 Proxy,访问任意属性(包括 then)都会被当成事件名,所以不能直接把它交给 Promise resolve
// 否则 Promise 会去调它的 then 而永远不落定;这里用对象包一层。
function waitForTracker(): Promise<{ tracker: LandingTracker | null }> {
return new Promise((resolve) => {
const startedAt = Date.now()
const check = () => {
const tracker = (window as any).tracker as LandingTracker | undefined
if (tracker && typeof tracker.landingPageView === 'function') {
resolve({ tracker })
return
}
if (Date.now() - startedAt > SDK_READY_TIMEOUT_MS) {
resolve({ tracker: null })
return
}
setTimeout(check, SDK_POLL_MS)
}
check()
})
}
/**
* 事件上报服务类
*/
export class EventTracker {
/**
* 发送事件到服务器
*/
async sendEvent(eventCode: EventCode, properties?: Record<string, any>) {
const { tracker } = await waitForTracker()
if (!tracker) {
console.log('LandingSDK 未就绪,事件丢弃:' + eventCode)
return
}
try {
if (eventCode === 'landing_page_view' && typeof tracker.landingPageView === 'function') {
await tracker.landingPageView(properties)
} else if (eventCode === 'landing_page_click' && typeof tracker.landingPageClick === 'function') {
await tracker.landingPageClick(properties)
} else {
await tracker({ event: eventCode, ...properties })
}
} catch (err) {
console.log('埋点上报失败:' + eventCode + ' ' + err)
}
}
}
// 单例实例
let trackerInstance: EventTracker | null = null
/**
* 获取事件上报器实例(自动初始化,无需手动初始化)
*/
export function getEventTracker(): EventTracker {
if (!trackerInstance) {
trackerInstance = new EventTracker()
}
return trackerInstance
}