tradingView-webSocket进阶——Vue.js

前几天写了一篇关于tradingView和webSocket的文章传送门,由于代码自己还在整合中,因此比较混乱,并且也没有demo能够运行。
这两天在GitHub上面看到了一个vue写的demo,仔细对比,原来就是我获得的最第一版本的tradingView-webSocket代码,很开心,觉得能够直接嵌入项目中,省了一番功夫。
然而现实是骨感的,这个demo并无写的太完善,该缺的功能同样仍是缺着的……传送门vue

无奈,仍是须要对这份代码进行加工。git

一、原demo分析

核心代码有4个文件:github

  1. index.vue
  2. datafees.js
  3. dataUpdater.js
  4. scoket.js

index是tradingView的实例化和用户行为的响应,属于业务逻辑实现。
datafees定义了实例化tradingview的对象,提供图表调用的方法,属于数据交互的接口。
dataUpdater是一个数据的触发器,当数据发生变化,经过dataUpdater来通知tradingview进行图表渲染,是业务逻辑和tradingview实例之间的通讯人。
scoket定义了webSocket的链接方式和数据收发的方法,是先后端数据交互的实现。web

功能缺乏,主要指业务逻辑实现上的功能缺乏。
缺乏的功能主要是历史记录获取、展现的功能。
初始化即获取1440条数据渲染到界面上,增量数据(实时交易记录)直接覆盖第1440条记录。
这样作的结果是,用户往左边拖拽的时候,不能展现更多的数据,同时,最新的增量数据的展现也是错位的。
另外,没有对webSocket的close事件进行监听,当链接关闭以后,增量更新即中止,这样的用户体验是不够的。
并且,初始化即获取1440条记录,将会致使初始化的时候须要请求的数据过多,查询时间和数据接收的时间都受影响,一样影响用户体验。segmentfault

二、index.vue详解

index.vue后端

created(){
    this.socket.doOpen()
    this.socket.on('open', () => {
      this.socket.send({ cmd: 'req', args: [`candle.M5.btcusdt}`, 1440, parseInt(Date.now() / 1000)] })
    })
    this.socket.on('message', this.onMessage)
}

在建立以后,链接socket,发送历史数据请求,从当前时间往回获取1440条数据,获取的是5分钟时间颗粒的btcusdt商品。而后监遵从webSocket返回的数据。数组

实例化tradingview:缓存

init(){}

经过webSocket发送数据:socket

sendMessage(){}

订阅实时交易数据:this

subscribe(){}

取消订阅实时交易数据:

unSubscribe(){}

以上方法,都是直接调用接口,下面是业务逻辑:

onMessage(data) {
      // console.log(data)
      if (data.data && data.data.length) {
        const list = []
        const ticker = `${this.symbol}-${this.interval}`
        data.data.forEach(function (element) {
          list.push({
            time: this.interval !== 'D' || this.interval !== '1D' ? element.id * 1000 : element.id,
            open: element.open,
            high: element.high,
            low: element.low,
            close: element.close,
            volume: element.quote_vol
          })
        }, this)
        this.cacheData[ticker] = list
        this.lastTime = list[list.length - 1].time
        this.subscribe()
      }
      if (data.type && data.type.indexOf(this.symbol.toLowerCase()) !== -1) {
        // console.log(' >> sub:', data.type)
        this.datafeeds.barsUpdater.updateData()
        const ticker = `${this.symbol}-${this.interval}`
        const barsData = {
          time: data.id * 1000,
          open: data.open,
          high: data.high,
          low: data.low,
          close: data.close,
          volume: data.quote_vol
        }
        if (barsData.time >= this.lastTime && this.cacheData[ticker] && this.cacheData[ticker].length) {
          this.cacheData[ticker][this.cacheData[ticker].length - 1] = barsData
        }
      }
    }

从socket接到数据,判断数据类型,若是是数组,表明的是历史数据,存入cacheData,记录时间,开始订阅增量数据。
若是不是数组,并且有type属性,表明的是增量数据,通知图表插件渲染数据,替换cacheData的最后一个元素。

下面的方法,是图表插件查询数据的时候使用:

getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback) {
      // console.log(' >> :', rangeStartDate, rangeEndDate)
      if (this.interval !== resolution) {
        this.unSubscribe(this.interval)
        this.interval = resolution
        if (resolution < 60) {
          this.sendMessage({ cmd: 'req', args: [`candle.M${this.interval}.${this.symbol.toLowerCase()}`, 1440, parseInt(Date.now() / 1000)] })
        } else if (resolution >= 60) {
          this.sendMessage({ cmd: 'req', args: [`candle.H${this.interval / 60}.${this.symbol.toLowerCase()}`, 1440, parseInt(Date.now() / 1000)] })
        } else {
          this.sendMessage({ cmd: 'req', args: [`candle.D1.${this.symbol.toLowerCase()}`, 800, parseInt(Date.now() / 1000)] })
        }
      }
      const ticker = `${this.symbol}-${this.interval}`
      if (this.cacheData[ticker] && this.cacheData[ticker].length) {
        this.isLoading = false
        const newBars = []
        this.cacheData[ticker].forEach(item => {
          if (item.time >= rangeStartDate * 1000 && item.time <= rangeEndDate * 1000) {
            newBars.push(item)
          }
        })
        onLoadedCallback(newBars)
      } else {
        const self = this
        this.getBarTimer = setTimeout(function () {
          self.getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback)
        }, 10)
      }
    }

若是图表插件查询的时候,resolution不一样,则表示用户切换了时间颗粒,须要取消订阅,修改interval,从新获取历史记录。
查询缓存cacheData是否为空,若是为空,表示数据尚未下发,10ms后再查询一次。
若是cacheData有数据,取到当前数据,执行回调onLoadedCallback。

三、结尾

如上,代码已经分析完了,至于怎么修改,未完待续!

相关文章
相关标签/搜索