前几天写了一篇关于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。
如上,代码已经分析完了,至于怎么修改,未完待续!