vue2集成JSSDK优化路程

911 阅读3分钟

最近突然想起来在前公司做的一个业务场景,觉得挺有意思的,在这次优化的过程中也能对于Vue的生命周期有更深的理解。

1.原始的JSSDK介绍

JSSDK功能点介绍 我们做了一款JSSDK,内部的实现是在SDK加载的时候,会在当前页面创建一个iframe页面,在iframe页面会进行canvas等绘图(绘图会有时间损耗),获取一些信息,然后上报到服务器,在进行Vue集成到时候遇到一些问题,本身iframe信息采集也是需要耗时的,所以在采集完成的时候,SDK会回调一个函数callback,进行通知主页面;也提供了主动调用SDK的方法,

JSSDK功能点.png

2.客户需求:

  1. 在应用的支付页面的时候首屏进行加载SDK,并且执行SDK的信息上报
  2. 并且在其他地方可以自主触发上报信息接口
  3. 使用vue框架进行集成,并且写出demo

3.技术分析:

  1. 由于JSSDK加载比较耗时,所以选择在集成的时候,在应用初始化的时候集成,避免需要重复集成
  2. 考虑到用户可能使用到懒加载,需要考虑在首页完整的执行机制
  3. JSSDK采集信息发送到服务器,是需要时间,需要进行控制,并且能准确的通知用户是否能进行重新生成sessionId
  4. 由于回调函数通知的时候,是全局的函数,所以回调函数做成一个回调队列,防止回调错乱
  5. 重新集成的时候(updateSessionID)需要判断当前的dom是否有指定ID的iframe
  6. 在app.vue页面进行初始化,在首屏页面需要等待初始化完成之后才可以进行首页的更新

4.实现思路

  1. 封装一个util/pagegis文件,对外暴露两个方法,init 、uploadSessionID
  2. init方法动态创建script标签,引入js,将callback的回调函数设置队列栈:callbackStack = {};key为当前生成的sessionId、value为回调函数Function;设置标志符:payegisKey
  3. update方法判断当前页面是否存在id为pagegis的iframe,以及 payegisKey,进而在判断是否是初始化还是执行更新的方法

JSSDK前端Vue接入流程图.drawio.png (JSSDK封装集成业务流程图)

const appId = 'XXXXXXX'
const baseUrl = 'http://localhost:8080' // 此处是JSSDK 对应的后台地址
let lastRandomId = null
const payegisKey = 'payegis_is_init'
localStorage.setItem(payegisKey, false)

// 随机字符串
function randomString (len) {
  len = len || 32
  const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
  const maxPos = $chars.length
  let pwd = ''
  for (let i = 0; i < len; i++) {
    pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
  }
  return pwd
}

// push callback to stack
const callbackStack = {}

function updateSessionId (callback) {
  if (localStorage.getItem(payegisKey) === 'false') return
  lastRandomId = randomString(32) // 此处是再次随机生成Id, 也可以自主传参数
  window.payegis.uploadSessionID(lastRandomId); // JSSDK 对外暴露的更新方法
  if (callback) {
    callbackStack[lastRandomId] = callback // 推栈
  }
}
const payegis = {
  // 设备指纹初始化
  init (callback) {
    const iframes = document.getElementsByTagName('iframe')
    const arr = Array.from(iframes).map(item => item.getAttribute('id')) || []
    if (arr.includes('payegisIfm')) {
      this.uploadSessionID(callback, true)
      return
    }
    if (localStorage.getItem(payegisKey) === 'false') {
      window.isOk = function (res) {
        if(localStorage.getItem(payegisKey) === 'false') {
          localStorage.setItem(payegisKey, true)
        }
        if (callbackStack.hasOwnProperty(lastRandomId)) {
          callbackStack[lastRandomId](res)
        }
      }
      lastRandomId = randomString(32)
      const ts = new Date().getTime() // 当前的时间戳
      const url = `${baseUrl}/did/js/dp.js?appId=${appId}&sessionId=${lastRandomId}&ts=${ts}&callback=isOk`
      // 动态生成js标签
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.src = url
      document.body.append(script)
      if (callback) {
        callbackStack[lastRandomId] = callback
      }
    } else {
      console.log('payegis is initialized')
    }
  },
  // 重新生成设备指纹
  uploadSessionID (callback, isCheck = false) {
    let arr = []
    if (!isCheck) {
      const iframes = document.getElementsByTagName('iframe')
      arr = Array.from(iframes).map(item => item.getAttribute('id')) || []
    }
    if (isCheck || (arr.includes('payegisIfm') && localStorage.getItem(payegisKey) === 'true')) {
      updateSessionId(callback)
    } else {
      this.init(callback)
    }
  }
}

export default payegis

app_vue.png

index.vue.png

5.vue应用初始化和首页初始化的加载机制

1.路由正常加载执行顺序 路由正常加载执行顺序.jpg

2.路由懒加载执行顺序

路由懒加载路由执行顺序.jpg 3.疑问: 我用vue-cli初始化项目加载顺序是上述,但是我用ruo-yi框架的vue前端使用懒加载和不使用懒加载,加载顺序都是第二种,这个问题未搞明白,要是有大佬清楚,可以在评论区评论。。

写在最后

我是crazyu,一位前端开发工程师。

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
  • 本文首发于微信公众号:crazyu 前端,未经许可禁止转载