前幾天寫了一篇關於tradingView和webSocket的文章傳送門,由於代碼自己還在整合中,因此比較混亂,並且也沒有demo能夠運行。
這兩天在GitHub上面看到了一個vue寫的demo,仔細對比,原來就是我獲得的最第一版本的tradingView-webSocket代碼,很開心,覺得能夠直接嵌入項目中,省了一番功夫。
然而現實是骨感的,這個demo並無寫的太完善,該缺的功能同樣仍是缺着的……傳送門。vue
無奈,仍是須要對這份代碼進行加工。git
核心代碼有4個文件:github
index是tradingView的實例化和用戶行爲的響應,屬於業務邏輯實現。
datafees定義了實例化tradingview的對象,提供圖表調用的方法,屬於數據交互的接口。
dataUpdater是一個數據的觸發器,當數據發生變化,經過dataUpdater來通知tradingview進行圖表渲染,是業務邏輯和tradingview實例之間的通訊人。
scoket定義了webSocket的鏈接方式和數據收發的方法,是先後端數據交互的實現。web
功能缺乏,主要指業務邏輯實現上的功能缺乏。
缺乏的功能主要是歷史記錄獲取、展現的功能。
初始化即獲取1440條數據渲染到界面上,增量數據(實時交易記錄)直接覆蓋第1440條記錄。
這樣作的結果是,用戶往左邊拖拽的時候,不能展現更多的數據,同時,最新的增量數據的展現也是錯位的。
另外,沒有對webSocket的close事件進行監聽,當鏈接關閉以後,增量更新即中止,這樣的用戶體驗是不夠的。
並且,初始化即獲取1440條記錄,將會致使初始化的時候須要請求的數據過多,查詢時間和數據接收的時間都受影響,一樣影響用戶體驗。segmentfault
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。
如上,代碼已經分析完了,至於怎麼修改,未完待續!