成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

tradingview-websocket進(jìn)階

Cc_2011 / 1651人閱讀

摘要:用戶量量大,數(shù)據(jù)量大,而且要求實(shí)時(shí)更新數(shù)據(jù)的時(shí)候,需要使用。該方法接收的有兩種,一種是數(shù)組。是歷史數(shù)據(jù),時(shí)間段的數(shù)據(jù),根據(jù)時(shí)間顆粒來(lái)劃分。

1、websocket

用戶量量大,數(shù)據(jù)量大,而且要求實(shí)時(shí)更新數(shù)據(jù)的時(shí)候,需要使用websocket。
tradingview正好就是這樣的應(yīng)用場(chǎng)景。

2、tradingview和websocket結(jié)合

getBars方法。tradingview圖表插件響應(yīng)用戶操作,根據(jù)用戶界面渲染需要的數(shù)據(jù)時(shí)間段,調(diào)用getBars方法,傳遞參數(shù)function(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback),我們需要構(gòu)造出預(yù)期的參數(shù)返回給onLoadedCallback方法,即onLoadedCallback(data)。

onLoadedCallback方法。該方法接收的data有兩種,一種是list數(shù)組。另一種是newBars對(duì)象。list是歷史數(shù)據(jù),rangeStartDate - rangeEndDate時(shí)間段的數(shù)據(jù),根據(jù)時(shí)間顆粒resolution來(lái)劃分。newBars是增量數(shù)據(jù),同樣是rangeStartDate - rangeEndDate時(shí)間段的數(shù)據(jù),但是這個(gè)數(shù)據(jù)必定是在當(dāng)前的resolution內(nèi)。當(dāng)我們把數(shù)據(jù)返回給onLoadedCallback,圖表會(huì)渲染這些數(shù)據(jù)。

3、數(shù)據(jù)獲取和填充

頁(yè)面初始化,實(shí)例化圖表,連接websocket。

從websocket得到的數(shù)據(jù)存入緩存cacheData。

因?yàn)間etBars是圖表自己調(diào)用的,所以當(dāng)我們存入數(shù)據(jù)到cacheData的時(shí)候,在getBars方法中調(diào)用onLoadedCallback就可以。

4、實(shí)例

圖表調(diào)用的getBars方法:

TVjsApi.prototype.getBars = function(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback) {
    //console.log(" >> :", this.formatt(rangeStartDate*1000), this.formatt(rangeEndDate*1000))
    var ticker = this.symbol + "-" + resolution;
    var tickerload = ticker + "load";
    var tickerstate = ticker + "state";

    if(!this.cacheData[ticker] && !this.cacheData[tickerstate]){
        //如果緩存沒(méi)有數(shù)據(jù),而且未發(fā)出請(qǐng)求,記錄當(dāng)前節(jié)點(diǎn)開(kāi)始時(shí)間
        this.cacheData[tickerload] = rangeStartDate;
        //發(fā)起請(qǐng)求,從websocket獲取當(dāng)前時(shí)間段的數(shù)據(jù)
        this.initMessage(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback);
        //設(shè)置狀態(tài)為true
        this.cacheData[tickerstate] = !0;
        return false;
    }

    if(!this.cacheData[tickerload] || this.cacheData[tickerload] > rangeStartDate){
        //如果緩存有數(shù)據(jù),但是沒(méi)有當(dāng)前時(shí)間段的數(shù)據(jù),更新當(dāng)前節(jié)點(diǎn)時(shí)間
        this.cacheData[tickerload] = rangeStartDate;
        //發(fā)起請(qǐng)求,從websocket獲取當(dāng)前時(shí)間段的數(shù)據(jù)
        this.initMessage(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback);
        //設(shè)置狀態(tài)為true
        this.cacheData[tickerstate] = !0;
        return false;
    }
    if(this.cacheData[tickerstate]){
        //正在從websocket獲取數(shù)據(jù),禁止一切操作
        return false;
    }
    //ticker = this.symbol + "-" + this.interval;
    //如果緩存有數(shù)據(jù),且長(zhǎng)度不為0,構(gòu)造數(shù)據(jù)
    if (this.cacheData[ticker] && this.cacheData[ticker].length) {
        this.isLoading = false
        var newBars = []
        this.cacheData[ticker].forEach(item => {
            if (item.time >= rangeStartDate * 1000 && item.time <= rangeEndDate * 1000) {
                newBars.push(item)
            }
        })
        onLoadedCallback(newBars)
    } else {
    //如果沒(méi)有數(shù)據(jù),等待10ms,再執(zhí)行一次
        var self = this
        this.getBarTimer = setTimeout(function() {
            self.getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback)
        }, 10)
    }
}

獲取歷史數(shù)據(jù)list的init方法:

TVjsApi.prototype.initMessage = function(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback){
    //console.log("發(fā)起請(qǐng)求,從websocket獲取當(dāng)前時(shí)間段的數(shù)據(jù)");
    var that = this;
    //保留當(dāng)前回調(diào)
    that.cacheData["onLoadedCallback"] = onLoadedCallback;
    //獲取需要請(qǐng)求的數(shù)據(jù)數(shù)目
    var limit = that.initLimit(resolution, rangeStartDate, rangeEndDate);
    //商品名
    var symbol = that.symbol;
    //如果當(dāng)前時(shí)間顆粒已經(jīng)改變,停止上一個(gè)時(shí)間顆粒的訂閱,修改時(shí)間節(jié)點(diǎn)值
    if(that.interval !== resolution){
        that.unSubscribe(that.interval)
        that.interval = resolution;
    }    
    //獲取當(dāng)前時(shí)間段的數(shù)據(jù),在onMessage中執(zhí)行回調(diào)onLoadedCallback
    if (that.interval < 60) {
        that.socket.send({
            cmd: "req",
            args: ["candle.M"+resolution+"."+symbol, limit, rangeEndDate],
            id: "trade.M"+ resolution +"."+ symbol.toLowerCase()
        })
    } else if (that.interval >= 60) {
        that.socket.send({
            cmd: "req",
            args: ["candle.H"+(resolution/60)+"."+symbol, limit, rangeEndDate],
            id: "trade.H"+ (resolution / 60) +"."+ symbol.toLowerCase()
        })
    } else {
        that.socket.send({
            cmd: "req",
            args: ["candle.D1."+symbol, limit, rangeEndDate],
            id: "trade.D1."+ symbol.toLowerCase()
        })
    }
}

響應(yīng)websocket的Message方法:

TVjsApi.prototype.onMessage = function(data) {
    var thats = this;
    //  console.log("這是后臺(tái)返回的數(shù)據(jù)"+count+":"+JSON.stringify(data) )
    
    if (data.data && data.data.length) {
        //websocket返回的值,數(shù)組代表時(shí)間段歷史數(shù)據(jù),不是增量
        var list = []
        var ticker = thats.symbol + "-" + thats.interval;
        var tickerstate = ticker + "state";
        
        //var that = thats;
        //遍歷數(shù)組,構(gòu)造緩存數(shù)據(jù)
        data.data.forEach(function(element) {
            list.push({
                time: element.id*1000,
                open: element.open,
                high: element.high,
                low: element.low,
                close: element.close,
                volume: element.quote_vol
            })
        }, thats)
        //如果沒(méi)有緩存數(shù)據(jù),則直接填充,發(fā)起訂閱
        if(!thats.cacheData[ticker]){
            /*thats.cacheData[ticker] = thats.cacheData[ticker].concat(list);
            thats.cacheData["onLoadedCallback"](list);
        }else{*/
            thats.cacheData[ticker] = list;
            thats.subscribe()
        }
        //新數(shù)據(jù)即當(dāng)前時(shí)間段需要的數(shù)據(jù),直接喂給圖表插件
        if(thats.cacheData["onLoadedCallback"]){
            thats.cacheData["onLoadedCallback"](list);
        }
        //請(qǐng)求完成,設(shè)置狀態(tài)為false
        thats.cacheData[tickerstate] = !1;
        //記錄當(dāng)前緩存時(shí)間,即數(shù)組最后一位的時(shí)間
        thats.lastTime = thats.cacheData[ticker][thats.cacheData[ticker].length - 1].time            
    }
    if (data.type && data.type.indexOf(thats.symbol.toLowerCase()) !== -1) {
        // console.log(" >> sub:", data.type)
        // data帶有type,即返回的是訂閱數(shù)據(jù),
        //緩存的key
        var ticker = thats.symbol + "-" + thats.interval;
        //構(gòu)造增量更新數(shù)據(jù)
        var barsData = {
            time: data.id * 1000,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            volume: data.quote_vol
        }
        /*if (barsData.time >= thats.lastTime && thats.cacheData[ticker] && thats.cacheData[ticker].length) {
            thats.cacheData[ticker][thats.cacheData[ticker].length - 1] = barsData
        }*/
        //如果增量更新數(shù)據(jù)的時(shí)間大于緩存時(shí)間,而且緩存有數(shù)據(jù),數(shù)據(jù)長(zhǎng)度大于0
        if (barsData.time > thats.lastTime && thats.cacheData[ticker] && thats.cacheData[ticker].length) {
            //增量更新的數(shù)據(jù)直接加入緩存數(shù)組
            thats.cacheData[ticker].push(barsData)
            //修改緩存時(shí)間
            thats.lastTime = barsData.time
        }else if(barsData.time == thats.lastTime && thats.cacheData[ticker].length){
            //如果增量更新的時(shí)間等于緩存時(shí)間,即在當(dāng)前時(shí)間顆粒內(nèi)產(chǎn)生了新數(shù)據(jù),更新當(dāng)前數(shù)據(jù)
            thats.cacheData[ticker][thats.cacheData[ticker].length - 1] = barsData
        }
        // 通知圖表插件,可以開(kāi)始增量更新的渲染了
        thats.datafeeds.barsUpdater.updateData()
    }
}

代碼邏輯如下:

getBars方法由圖表插件調(diào)用,帶有當(dāng)前需要渲染的時(shí)間參數(shù)、時(shí)間顆粒和callback。

如果緩存中有當(dāng)前時(shí)間段的數(shù)據(jù),構(gòu)造newBars,調(diào)用onLoadedCallback(newBars)。

如果緩存中沒(méi)有數(shù)據(jù),判斷當(dāng)前需要的數(shù)據(jù)類型,如果是list歷史記錄,那么我們需要通過(guò)websocket來(lái)獲取,執(zhí)行initMessage。

判斷當(dāng)前緩存中的時(shí)間顆粒resolution是否已經(jīng)改變,如果已經(jīng)改變,需要清除緩存數(shù)據(jù),更新緩存cacheData = list,返回圖表onLoadedCallback(list),另外需要訂閱當(dāng)前時(shí)間顆粒的增量數(shù)據(jù),取消上一次訂閱。

如果時(shí)間顆粒resolution沒(méi)有改變,websocket得到的歷史數(shù)據(jù)不需要存入緩存,直接調(diào)用onLoadedCallback(list)就可以,因?yàn)閳D表插件的渲染是根本得到的數(shù)據(jù)時(shí)間段來(lái)執(zhí)行的,即:圖表插件會(huì)緩存已經(jīng)渲染過(guò)的數(shù)據(jù)。

如果當(dāng)前請(qǐng)求的數(shù)據(jù)為增量數(shù)據(jù),但是緩存中沒(méi)有,等待10ms,因?yàn)樵隽繑?shù)據(jù)來(lái)源于websocket,我們已經(jīng)訂閱,需要等待websocket返回,相當(dāng)于pending。

以上邏輯基本含括了用戶的兩個(gè)重要操作:切換時(shí)間顆粒、查看歷史記錄。
可運(yùn)行代碼在GitHub上已經(jīng)更新,可預(yù)覽。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/99049.html

相關(guān)文章

  • tradingView-webSocket進(jìn)階——Vue.js

    摘要:無(wú)奈,還是需要對(duì)這份代碼進(jìn)行加工。功能缺少,主要指業(yè)務(wù)邏輯實(shí)現(xiàn)上的功能缺少。缺少的功能主要是歷史記錄獲取展示的功能。查詢緩存是否為空,如果為空,表示數(shù)據(jù)還沒(méi)有下發(fā),后再查詢一次。如果有數(shù)據(jù),取到當(dāng)前數(shù)據(jù),執(zhí)行回調(diào)。 前幾天寫(xiě)了一篇關(guān)于tradingView和webSocket的文章傳送門(mén),因?yàn)榇a本身還在整合中,所以比較混亂,而且也沒(méi)有demo可以運(yùn)行。這兩天在GitHub上面看到了一...

    levius 評(píng)論0 收藏0
  • 進(jìn)階1-3期】JavaScript深入之內(nèi)存空間詳細(xì)圖解

    摘要:進(jìn)階期理解中的執(zhí)行上下文和執(zhí)行棧進(jìn)階期深入之執(zhí)行上下文棧和變量對(duì)象但是今天補(bǔ)充一個(gè)知識(shí)點(diǎn)某些情況下,調(diào)用堆棧中函數(shù)調(diào)用的數(shù)量超出了調(diào)用堆棧的實(shí)際大小,瀏覽器會(huì)拋出一個(gè)錯(cuò)誤終止運(yùn)行。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第3天。 本計(jì)劃一共28期,每期重點(diǎn)攻...

    coordinate35 評(píng)論0 收藏0
  • 進(jìn)階1-2期】JavaScript深入之執(zhí)行上下文棧和變量對(duì)象

    摘要:本計(jì)劃一共期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)劃,點(diǎn)擊查看前端進(jìn)階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對(duì)象,由于微信不能訪問(wèn)外鏈,點(diǎn)擊閱讀原文就可以啦。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計(jì)劃一共28期,每期...

    Richard_Gao 評(píng)論0 收藏0
  • 進(jìn)階2-2期】JavaScript深入之從作用域鏈理解閉包

    摘要:使用上一篇文章的例子來(lái)說(shuō)明下自由變量進(jìn)階期深入淺出圖解作用域鏈和閉包訪問(wèn)外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第7天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)...

    simpleapples 評(píng)論0 收藏0
  • 進(jìn)階1-1期】理解JavaScript 中的執(zhí)行上下文和執(zhí)行棧

    摘要:首次運(yùn)行代碼時(shí),會(huì)創(chuàng)建一個(gè)全局執(zhí)行上下文并到當(dāng)前的執(zhí)行棧中。執(zhí)行上下文的創(chuàng)建執(zhí)行上下文分兩個(gè)階段創(chuàng)建創(chuàng)建階段執(zhí)行階段創(chuàng)建階段確定的值,也被稱為。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,,今天是第一天 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)...

    import. 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<