tradingView-webSocket進階——Vue.js

前幾天寫了一篇關於tradingView和webSocket的文章傳送門,因爲代碼本身還在整合中,所以比較混亂,而且也沒有demo可以運行。
這兩天在GitHub上面看到了一個vue寫的demo,仔細對比,原來就是我得到的最初版本的tradingView-webSocket代碼,很開心,以爲可以直接嵌入項目中,省了一番功夫。
然而現實是骨感的,這個demo並沒有寫的太完善,該缺的功能一樣還是缺着的……傳送門

無奈,還是需要對這份代碼進行加工。

1、原demo分析

核心代碼有4個文件:

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

index是tradingView的實例化和用戶行爲的響應,屬於業務邏輯實現。
datafees定義了實例化tradingview的對象,提供圖表調用的方法,屬於數據交互的接口。
dataUpdater是一個數據的觸發器,當數據發生變化,通過dataUpdater來通知tradingview進行圖表渲染,是業務邏輯和tradingview實例之間的通信人。
scoket定義了webSocket的連接方式和數據收發的方法,是前後端數據交互的實現。

功能缺少,主要指業務邏輯實現上的功能缺少。
缺少的功能主要是歷史記錄獲取、展示的功能。
初始化即獲取1440條數據渲染到界面上,增量數據(實時交易記錄)直接覆蓋第1440條記錄。
這樣做的結果是,用戶往左邊拖拽的時候,不能展示更多的數據,同時,最新的增量數據的展示也是錯位的。
另外,沒有對webSocket的close事件進行監聽,當連接關閉之後,增量更新即停止,這樣的用戶體驗是不夠的。
而且,初始化即獲取1440條記錄,將會導致初始化的時候需要請求的數據過多,查詢時間和數據接收的時間都受影響,同樣影響用戶體驗。

2、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發送數據:

sendMessage(){}

訂閱實時交易數據:

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。

3、結尾

如上,代碼已經分析完了,至於怎麼修改,未完待續!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章