递归java脚本函数 - 失控

时间:2016-08-24 16:26:01

标签: javascript node.js recursion

以下代码有效。代码调用API来获取历史交易(每次拉动时交易100次)。因为有一个限制 - 我允许调用API的次数和频率 - 结构就像递归一样。

流程如下:

  1. 获取当前的MAX tradeId - 存储在数据库中。
  2. 现在使用startIndex = MaxId和100的长度(以提取100个新交易)进行新的PULL。
  3. 首先调用回调函数时,主代码继续,并且拉出100个新交易...等等。等。
  4. 因此...

    代码应该像 - Psydo-code

    var maxId = GetMaxIdFromDB();
    
    Pull(maxId, 100, callback);
    
    function callback(){
    
    ... do different stuff..
    maxId += 100;
    
    Pull(maxId, 100, callback);
    
    }
    

    奇怪的是,我的问题是:如何多次调用API函数“ getProductTrades ” - 我的游标变量包含 SAME值 - 当它增加100(或每次有效数据元素的数量)时。

    我在说/参考。特别是以下几行:

    wl.debug("getProductTrades - cursor: " + cursor + " Limit: " + limit);
                    publicClient.getProductTrades({'after': cursor, 'limit': limit}, callback);
    

    insertQuery.InsertMatchMsgArrayToDB(allData); 方法调用另一个返回promise的DB方法。

    您可以在此处查看问题的屏幕截图: http://screencast.com/t/DH8rz3UxnyZ

    真正的代码在这里:

    pullTradesBetween: function (minTradeId, maxTradeId) {
    
                var wl = new WinLog();
                var tradeCounter = 0;
    
                try {
                    var WebSocketEmit = new WSemitter();
                    var startTime = new Date().toLocaleString();
                    var executeTradePullAgain = null;
    
                    wl.debug("REST API START: " + startTime);
    
                    var cursor;
                    var incrementedCursorWith = 0;
    
                    if ((maxTradeId - minTradeId) < 100) {
                        cursor = maxTradeId + 1;
                    }
                    else
                        cursor = minTradeId + 100;
    
                    var callback = function (err, response, data) {
    
                        if (executeTradePullAgain !== null)
                            clearTimeout(executeTradePullAgain);
    
                        if (err)
                            wl.info("Err: " + err);
    
                        var validData = [];
                        incrementedCursorWith = 0;
    
                        if (response == null)
                            wl.info("RESPONSE ER NULL");
    
                        if (data !== null) {
                            for (var i = data.length - 1; i >= 0; i--) {
                                var obj = data[i];
    
                                var tradeId = parseInt(obj.trade_id);
    
                                if (obj !== null && (minTradeId <= tradeId && tradeId <= maxTradeId)) {
                                    validData.push(data[i]);
                                }
                            }
    
                            if (validData.length == 0) {
                                wl.debug("Contains 0 elements!");
                            }
                            else {
                                cursor = cursor + validData.length;
                                incrementedCursorWith = validData.length;
                                insertDataToDB(validData);
                            }
                        }
                        else
                            wl.debug("DATA IS NULL!");
    
                        wl.debug("cursor: " + cursor + " maxTradeId: " + maxTradeId);
    
                        var diffToMax = maxTradeId - (cursor - incrementedCursorWith);
    
                        if (diffToMax >= 100)
                            pullTrades(cursor, 100); // 100 is default
                        else if (diffToMax >= 0)
                            pullTrades(maxTradeId + 1, diffToMax + 1); // X = Only the last trades in the given series of trades
                        else {
                            wl.info("REST API START: " + startTime + " REST API DONE: " + new Date().toLocaleString());
    
                            WebSocketEmit.syncHistoricalDataDone();
                        }
                    };
    
                    function pullTrades(cursor, limit) {
    
                        tradeCounter += limit;
    
                        if(tradeCounter % 10000 == 0){
                            wl.info('Downloaded: ' + tradeCounter + ' trades via REST API (Total: ' + cursor + ')');
                        }
    
                        pullTradesAgainIfServerDoesNotRespond(cursor, limit);
    
                        wl.debug("getProductTrades - cursor: " + cursor + " Limit: " + limit);
                        publicClient.getProductTrades({'after': cursor, 'limit': limit}, callback);
                    }
    
                    function pullTradesAgainIfServerDoesNotRespond(cursor, limit) {
    
                        executeTradePullAgain = setTimeout(function () {
                            wl.debug('pullTradesAgainIfServerDoesNotRespond called!');
                            pullTrades(cursor, limit);
                        }, 30000);
                    }
    
                    // SAVE DATA IN DB!
                    function insertDataToDB(allData) {
                        insertQuery.InsertMatchMsgArrayToDB(allData);
                    }
    
                    wl.debug("pull trades: " + cursor);
                    pullTrades(cursor, 100);
                }
                catch(err){
                    wl.info('pullTradesBetween: ' + err);
                } }};
    

2 个答案:

答案 0 :(得分:1)

当您没有getProductionTrades的数据时,就会发生这种情况。 如果返回的数据为null,则永远不会到达

cursor = cursor + validData.length;
incrementedCursorWith = validData.length;

但你还是打电话

pullTrades(cursor, 100);

最后。我不知道它的意图或实际错误,所以我将解决方案(现在应该是微不足道的)留给你了。

答案 1 :(得分:0)

我尝试简化您的代码

pullTradesBetween: function (minTradeId, maxTradeId) {
    var WebSocketEmit = new WSemitter(); // try-catch ?
    var curr = (maxTradeId - minTradeId < 100) ? maxTradeId + 1 : minTradeId + 100;

    // function always return data or infinite error-loop
    function getProductTrades (after, limit, callback) {
        // try-catch ?
        publicClient.getProductTrades ({after, limit}, function(err, data) {
            if (err) {
                console.log(err);
                return getTrades(after, limit, callback);
            }

            callback(null, data);
        });
    }

    function onDataReady (err, data) {
        if (err)
            throw new Error('Impossible!');

        if (!data || !(data instanceof Array))  
            return ... smth on empty data ...

        var validData = data.filter(function(obj) {
            return obj && 
                minTradeId <= parseInt(obj.trade_id) &&
                parseInt(obj.trade_id) <= maxTradeId;
        }).reverse();

        if (validData.length == 0)
            return ... smth on empty data ...

        insertDataToDB(validData);

        curr += validData.length; // maybe +-1 

        var remaining = maxTradeId - curr;
        if (remainig == 0) {
            console.log('Done');
            // try-catch ?
            WebSocketEmit.syncHistoricalDataDone();
        }

        return (remaining >= 100) ? 
            getProductTrades(curr, 100, onDataReady) : 
            getProductTrades(maxTradeId + 1, remaining + 1, onDataReady); // ??
    }

    getProductTrades(curr, 100, onDataReady);
}