doufei3152 2018-06-19 18:39
浏览 577
已采纳

XHR请求失败 - 网络选项卡中的待处理/取消,站点运行缓慢

Inherited ECommerce platform with custom built Ajax JS system is failing to respond. Link: http://www.bebeautifulsalonandspa.com/store/checkout/

Go into the store and add a product, then try to enter your postal code and lookup rates. Postal code lookup is not responding. Looking for assistance with the debug, I've hit a wall. I know the response from Canada Post is coming back okay into PHP land. Sample dump of Array in PHP land before returning:

Array
(
    [0] => Array
        (
            [type] => Expedited Parcel
            [price] => 10.95
            [estimatedDeliveryDate] => 2018-06-19
            [estimatedDeliveryDays] => 1
        )

    [1] => Array
        (
            [type] => Priority
            [price] => 22.26
            [estimatedDeliveryDate] => 2018-06-19
            [estimatedDeliveryDays] => 1
        )

    [2] => Array
        (
            [type] => Regular Parcel
            [price] => 10.95
            [estimatedDeliveryDate] => 2018-06-20
            [estimatedDeliveryDays] => 2
        )

    [3] => Array
        (
            [type] => Xpresspost
            [price] => 11.73
            [estimatedDeliveryDate] => 2018-06-19
            [estimatedDeliveryDays] => 1
        )

)

This same system seems to be working okay on another website. I've tried copy pasting the other site's JS, PHP, HTML into this site and it is still failing to respond.

The JS code that is running the Ajax request is many files and I have no idea what part would need to be pasted here, honestly.

If you were me, where would you look first?

EDITS: Some of the code here...it's a completely custom "system" across like 10 files however. This is the piece that is the core system that runs generic Ajax requests:

(function(EVO){
    EVO.LoadSingletonFactory('Ajax', Ajax);

    /* Currently this is an ugly piece of code and required refactoring and cleanup */
    function Ajax(){
        var interrupt = false;
        var processing = false;
        var currentRequest;
        var ajaxQ = [];
        var settings = {
            'requestHandler':'',
            'freezeDelay':2500,
            'timeout':10000,
            'method':'post',
            'flatten':false
        };
        var $return = {
            'Settings':SettingsAPI,
            'Send':Send
        };

        return $return;

        /* Public Methods */
        function SettingsAPI(){
            var $return = {
                'RequestHandler':RequestHandler,
                'FreezeDelay':FreezeDelay,
                'Method':Method,
                'Timeout':Timeout
            };
            return $return;

            function RequestHandler(_urlOrFunction){
                if(_urlOrFunction){
                    settings.requestHandler = _urlOrFunction;
                }
                return settings.requestHandler;
            };

            function Timeout(_ms){
                if(EVO.Is(_ms) == 'number'){
                    settings.timeout = _ms;
                }
                return settings.timeout;
            };

            function FreezeDelay(_ms){
                if(EVO.Is(_ms) == 'number'){
                    settings.freezeDelay = _ms;
                }
                return settings.freezeDelay;
            };

            function Method(_method){
                if(EVO.Is(_method) == 'string'){
                    switch(_method.toLowerCase()){
                        case 'get': case 'post': case 'put':
                            settings.method = _method.toLowerCase();
                            break;
                    }
                }
                return settings.method;
            };

            function Flatten(_bool){
                if(_bool === true || _bool === false){
                    settings.flatten = _bool;
                }
                return settings.flatten;
            };

            function Format(_json){

            };
        };

        function Send(_json, _interrupt){
            if(_interrupt === true){
                interrupt = true;
                if(currentRequest){
                    currentRequest.cancel();
                }
                $return.Once('clearedQ', function(){
                    Send(_json);
                });
                startQ();
            }
            else{
                addRequestToQ(_json, copySettings(settings));
                if(!processing && ajaxQ.length){

                    startQ();
                }
            }
        };

        function Cancel(){
            if(processing && currentRequest){

                currentRequest.cancel();
                ajaxQ = [];
                processing = false;
            }
        };

        /* Private Methods */
        function addRequestToQ(_json, _settings){
            var add = true;

            for(var i=0,length=ajaxQ.length;i<length;i++){
                if(ajaxQ.json == _json && ajaxQ.settings == _settings){
                    add = false;
                    break;
                }
            }
            if(add){

                ajaxQ[ajaxQ.length] = {'json':_json, 'settings':_settings};
            }
        };

        function startQ(_fireQEvent){
            if(ajaxQ.shift && ajaxQ.length > 0 && !processing){
                var obj = ajaxQ.shift();
                if(interrupt){
                    startQ();
                }
                else{
                    currentRequest = startRequest(obj.json, obj.settings);
                }
            }
            else{
                interrupt = false;
                if(_fireQEvent !== false){
                    $return.Emit('clearedQ');
                }
            }
        };

        function startRequest(_data, _settings){
            var requestData,response,XHR;
            var timer = {};
            var $api = {
                'cancel':cancel
            };

            processing = true;
            if(EVO.Is(_settings.requestHandler) == 'string'){
                //XHR Request
                var XHR = initXHR();

                if(XHR){
                    requestData = setupMethod(XHR,_settings.method,_settings.requestHandler,_data,_settings.flatten);
                    if(!requestData){
                        requestData = '';
                    }
                    XHR.onreadystatechange = function(){
                        if(EVO.Is(XHR) != 'undefined' && XHR.readyState == 4){
                            //In theory our request has responded, but as we've found this doesn't work entirely how expected
                            try{
                                response = XHR.responseText;
                                try{
                                    response = JSON.parse(response);
                                }
                                catch(e){/*Parsing JSON would have failed.  Somehow.*/}
                                completeRequest(response);
                            }
                            catch(e){throw e;}
                        }
                    }
                    startRequestTimer();
                    XHR.send(requestData);
                    $return.Emit('request', $api);
                }
            }
            else{
                //We're in function land

                startRequestTimer();
                response = _settings.requestHandler.call(undefined,_data);
                if(EVO.Is(response) == 'object' && response.On && response.HandleRequest){

                    response.On('ready', function(responseData){

                        completeRequest(responseData);
                    });
                    response.HandleRequest(_data);
                }
                else{
                    completeRequest(response);
                }
            }

            return $api;

            /* request methods */
            function initXHR(){
                try { return new XMLHttpRequest(); } catch(e) {}
                try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
            };

            function setupMethod(_XHR, _method, _url, _data, _flatten){
                var $return,count,key,val,uri;
                switch(_method){
                    case 'post':
                        _XHR.open('post', _url, true);
                        _XHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                        if(_flatten && EVO.Is(_data) == 'object'){
                            count = 0;
                            $return = '';
                            for(var prop in _data){
                                key = prop;
                                val = (EVO.Is(_data[prop]) == 'object' ? JSON.stringify(_data[prop]) : _data[prop]);
                                $return = $return+(!count ? key+'='+val : '&'+key+'='+val);
                                count++;
                            }
                        }
                        else if(!_flatten && EVO.Is(_data) == 'object'){
                            $return = 'data='+(EVO.Is(_data) == 'object' ? JSON.stringify(_data) : _data);
                        }
                        else{
                            $return = 'data='+_data;
                        }
                        break;

                    case 'put':
                        _XHR.open('put', _url, true);
                        (EVO.Is(_data) == 'object' ? _XHR.setRequestHeader("Content-type", "application/json") : _XHR.setRequestHeader("Content-type", "text/plain"));
                        $return = _data;
                        break;

                    case 'get':
                        if(EVO.Is(_data) == 'object'){
                            count = 0;
                            uri = '';
                            for(var prop in _data){
                                if(_data.hasOwnProperty(prop)){
                                    key = encodeURIComponent(prop);
                                    if(EVO.Is(_data[prop] == 'object')){
                                        val = encodeURIComponent(JSON.stringify(_data[prop]).replace(/'|"/g,''));
                                        //val = _data[prop];
                                    }
                                    else if(EVO.Is(_data[prop] == 'string')){
                                        val = encodeURIComponent(_data[prop].replace(/'|"/g,''));
                                        //val = _data[prop];
                                    }
                                    else{
                                        val = '';
                                    }

                                    //val = (EVO.Is(_data[prop]) == 'object' ? encodeURIComponent(JSON.stringify(_data[prop])) : (EVO.Is(_data[prop]) == 'string' ? encodeURIComponent(_data[prop]) : ''));
                                    uri = uri+(!count ? "?"+key+'='+val : '&'+key+'='+val);
                                    count++;
                                }
                            }
                        }

                        _XHR.open('get', _url+uri, true);
                        break;
                }
                return $return;
            };          

            function startRequestTimer(){
                var D = new Date();
                timer.startTime = D.getTime();
                if(settings.freezeDelay){
                    timer.freezeTimer = setTimeout(function(){ $return.Emit('freeze', true); }, settings.freezeDelay);
                }

                if(settings.timeout){
                    timer.timeoutTimer = setTimeout(function(){ $return.Emit('timeout', _data); cancel(); }, settings.timeout)
                }
            };


            function cancel(){
                //Abort
                if(EVO.Is(XHR) == 'object' && XHR.abort){
                    XHR.aborted = true;
                    XHR.abort();
                }
                else if(EVO.Is(response) == 'object' && response.Emit){
                    response.Emit('abort', _data);
                }

                //Cancel our freeze
                requestData = undefined;
                response = undefined;
                if(timer.freezeTimer){
                    clearTimeout(timer.freezeTimer);
                }
                $return.Emit('freeze', false);
                if(timer.timeoutTimer){
                    clearTimeout(timer.timeoutTimer);
                }
                timer = {};
                currentRequest = undefined;
                XHR = undefined;
                processing = false;
            };

            function completeRequest(_response){
                //Cancel our freeze if it exists
                $return.Emit('freeze', false);

                //First we cancel our timers
                if(timer.freezeTimer){
                    clearTimeout(timer.freezeTimer);
                }
                if(timer.timeoutTimer){
                    clearTimeout(timer.timeoutTimer);
                }
                timer = {};

                //Now we kill our currentXHR
                currentRequest = undefined;

                //We Emit our response
                if(XHR){
                    if(processing && XHR.status !== 0){
                        $return.Emit('response', _response);
                    }
                }
                else{
                    $return.Emit('response', _response);
                }

                //We flag our processing to finished
                XHR = undefined;
                processing = false;

                //We let our Q take over
                startQ(false);
            };
        };

        function copySettings(_obj){
            var $return = {};
            if(EVO.Is(_obj) == 'object'){
                for(var prop in _obj){
                    if(_obj.hasOwnProperty(prop)){
                        $return[prop] = _obj[prop];
                    }
                }
            }
            return $return;
        };
    };
})(EVO);

This is the Checkout JS calling the Ajax system mentioned above.

EVO.DomJack().Ready(function(){
    var shippingSet = false;
    var ECQuantUpdate = EVO.Ajax('ECQuantity');
        ECQuantUpdate.Settings().RequestHandler('/_app/');

    var ECRedrawItems = EVO.Ajax('ECRedrawItems');
        ECRedrawItems.Settings().RequestHandler('/_app/');
    var ECRedrawSubtotal = EVO.Ajax('ECRedrawSubtotal');
        ECRedrawSubtotal.Settings().RequestHandler('/_app/');
    var ECRedrawCartTotal = EVO.Ajax('ECRedrawCartTotal');
        ECRedrawCartTotal.Settings().RequestHandler('/_app/');  

        function redraw(){
            ECRedrawItems.Send({
                'appAddress': 'ArraySoft/ECommerce',
                'name': 'GetMapJson',
                'mapVars': {'map': 'Checkout'},
                'mapName': 'cartItemMap',
                'autoMerge': true
            });
            ECRedrawSubtotal.Send({
                'appAddress': 'ArraySoft/ECommerce',
                'name': 'GetMapJson',
                'mapVars': {'map': 'Checkout'},
                'mapName': 'shippingMap',
                'autoMerge': true   
            });
            ECRedrawCartTotal.Send({
                'appAddress': 'ArraySoft/ECommerce',
                'name': 'GetMapJson',
                'mapVars': {'map': 'Checkout'},
                'mapName': 'cartItemMap',
                'autoMerge': false
            }); 

        };

        ECRedrawItems.On('response',function(data){
            EVO.Select('#itemContainer')[0].SetInner(data.mergedMap);
            bindButtons();
            rebindQuantity();
        });

        ECRedrawSubtotal.On('response',function(data){
            EVO.Select('#summaryContainer')[0].SetInner(data.mergedMap);
            EVO.Select('#subtotal .total')[0].SetInner("$"+data['data']['blocks'][1]['data']['subtotal']['1']);
        });
        ECRedrawCartTotal.On('response',function(_data){

        });


    function bindButtons(){
        var EDAJ = EVO.Ajax('EDAJ');
        EDAJ.Settings().RequestHandler('/_app/');
        EVO.Select('.itemList .delete_button').Each(function(){
            var _djThis = this;
            _djThis.On('click',function(){
                var itemId = _djThis.GetAttribute('data-itemId');
                if(itemId){
                    EDAJ.Send({
                        'appAddress':'ArraySoft/ECommerce',
                        'name':'publicUpdateItemInCartById',
                        'data': {
                            'itemId': itemId,
                            'qty': 0
                        }
                    })
                    EDAJ.Once('response',function(_data){
                        redraw();
                    });
                }
            });
        });
        EVO.Select('.itemList .subtract').Each(function(){
            var _djThis = this;
            _djThis.On('click',function(){
                var itemId = _djThis.GetAttribute('data-itemId');
                var input = EVO.Select('input',_djThis.GetParent().GetNode())[0];
                var val = parseInt(input.Value());

                input.Value((val - 1 < 0 ? 0 : val - 1));
                input.Emit('blur');
            });
        });
        EVO.Select('.itemList .add').Each(function(){
            var _djThis = this;
            _djThis.On('click',function(){
                var itemId = _djThis.GetAttribute('data-itemId');
                var input = EVO.Select('input',_djThis.GetParent().GetNode())[0];
                var val = parseInt(input.Value());
                input.Value(val + 1);
                input.Emit('blur');
            });
        });
    }   

    bindButtons();

    function rebindQuantity(){
        EVO.Select("input.number-item").Each(function(){
            var DJ = this;
            var SODJ = EVO.Select('#shippingOptions')[0];
            DJ.On('blur',function(){
                //Update quantity, and re-call shippingOptions.  Maybe store what the type was and attempt to restore it.
                var newQuantity = DJ.GetNode().value; //I don't know if DomJack is okay with Value() so let's be safe :)
                var itemID = DJ.GetAttribute('data-item-id');
                ECQuantUpdate.Send({
                    'appAddress':'ArraySoft/ECommerce',
                    'name': 'publicUpdateItemInCartById',
                    'data': {
                        'qty': newQuantity,
                        'itemId': itemID
                    }
                },true);
                ECQuantUpdate.Once('response',function(){
                    redraw();
                });
            });
        });
    }
    rebindQuantity();

    EVO.Select("#shipping form[name=shipping]")[0].On('submit',function(){
        waitingSpinner(true); //I triggered the spinner!

        var ECShipAJ = EVO.Ajax('ECShipAJ');
            ECShipAJ.Settings().RequestHandler('/_app/');
        var ECShipSelect = EVO.Ajax('ECShipSelect');
            ECShipSelect.Settings().RequestHandler('/_app/');

        var formData = this.Gather();
        //Lets validate the postal code and show a message.
        if(!(/[A-z][0-9][A-z][\s\-]*?[0-9][A-z][0-9]/.test(formData.postalCode))){
            promptInvalidPostalCode();
            return false;
        }
        ECShipAJ.Once('response',function(data){
            waitingSpinner(false); //I turned the spinner off!
            if(data.fail){
                alert('We were unable to get shipping prices for your order. If you are ordering in bulk - 4 or more units - please contact ');
                promptInvalidPostalCode();              
            }
            else{
                //console.log('Result received');
                var SODJ = EVO.Select('#shippingOptions')[0];
                //console.log(SODJ);
                var shippingOptions = generateShippingOptionsSelect(data);
                    shippingOptions.On('change',function(){
                        if(this.Value()){
                            ECShipSelect.Send({
                                    'appAddress':'ArraySoft/ECommerce',
                                    'name':'publicSetShippingOption',
                                    'data':{
                                        'postalCode': formData.postalCode,
                                        'price': shippingOptions.Value(),
                                        'type': EVO.DomJack(shippingOptions.GetSelected()).GetAttribute('data-shipping-type')
                                    }       
                            });
                            ECShipSelect.Once('response',function(data){
                                updateTotals(data.totals);
                            });
                            shippingSet = true;
                        }
                        else{
                            shippingSet = false;
                        }
                    });
                SODJ.Dump();
                var label = EVO.DomJack('span');
                    label.SetInner('Delivery Method: ');
                    label;
                SODJ.Append(label);
                SODJ.Append(shippingOptions);   
                $('#shippingOptions span').addClass('summary_label');
                $('#shippingOptions option').addClass('total');         
            }
        });

        ECShipAJ.Send({
                'appAddress':'ArraySoft/ECommerce',
                'name':'publicGetShippingRates',
                'data':{
                    'postalCode': formData.postalCode
                }
        });
        return false;
    });

    function promptInvalidPostalCode(){
            triggerMessage("Postal Code is invalid",3000);
            waitingSpinner(0);
    }

    function generateShippingOptionsSelect(shippingData){
        //console.log('shipping options');
        //console.log(shippingData);
        var ret = EVO.DomJack('select');

            ret.Append(EVO.DomJack('option').SetInner('Choose Shipping Option'));
        //  console.log('domjack error');
        if(EVO.Is(shippingData) == "array"){
            //console.log('is array');
            for(var i = 0; i < shippingData.length; i++){
                var current = shippingData[i];
                ret.Append(handleOption(current));
            }
        }else { /*console.log('not an array'); */}
        function handleOption(optionData){
        //  console.log('handling result option');
        //  console.log(optionData);
            var option = EVO.DomJack('option');
                option.SetAttribute('value',optionData.price);
                option.SetAttribute('data-shipping-type',optionData.type);
                option.SetInner(optionData.type + ' - ' + 
                                "Est Delivery: "+optionData.estimatedDeliveryDays+" day(s)");

            return option;
        }
        //console.log(ret);
        return ret;
    }

    function updateTotals(totalsData){
        EVO.Select('#total .total')[0].SetInner("$"+totalsData.grandTotal);
        EVO.Select('#taxes .total')[0].SetInner("$"+totalsData.taxTotal);
        EVO.Select('#shipping .total')[0].SetInner("$"+totalsData.shTotal);
        EVO.Select('#subtotal .total')[0].SetInner("$"+totalsData.subTotal);                
    }

    function addSubtract(condition){
        var inputVal = parseInt($('#input_'+inputID+' .number-item').attr('value'));
        if(condition == 1){
            inputVal = inputVal+1;
        }else{
            inputVal = inputVal-1;
        }
        $('#input_'+inputID+' .number-item').attr('value',inputVal);
        redraw();
        rebindQuantity();
    }

    function waitingSpinner(state){
        if(state){
            //console.log("I'm spinning!");
            $('#spinner').show();
        }
        else{
            //console.log("I'm not spinning :(");
            $('#spinner').hide();
        }
    }

     var reviewButton = EVO.Select('#review_button')[0];
     reviewButton.GetParent().On('click',function(){
        if(!shippingSet){
            //Do something pretty here that says shipping must be valid before checking out
            triggerMessage("Shipping must be valid before checking out",1000);
        }
        return shippingSet;
     });

/*
     reviewButton.Submit(function(){
        alert('test');
        return false;
     });

*/

});
function triggerMessage(msg,time){
    time = time || 1000;
    $('#shippingMessageWrap').html(msg);
    $('#shippingMessageContainer').fadeIn().delay(time).fadeOut();
}
  • 写回答

1条回答 默认 最新

  • duankanjian4642 2018-06-27 20:32
    关注

    I solved this in the end. The root cause was an over-inflated database table that had reached 19mb, ajax request was basically timing out. After I replaced the custom Ajax with jQuery, it was able to wait out the slow response and get data back. At that point the lightbulb went off and I realized it had to be database. Dumped the majority of that table and everything is happy again. Now to put some proper cleanup into this system!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 cgictest.cgi文件无法访问
  • ¥20 删除和修改功能无法调用
  • ¥15 kafka topic 所有分副本数修改
  • ¥15 小程序中fit格式等运动数据文件怎样实现可视化?(包含心率信息))
  • ¥15 如何利用mmdetection3d中的get_flops.py文件计算fcos3d方法的flops?
  • ¥40 串口调试助手打开串口后,keil5的代码就停止了
  • ¥15 电脑最近经常蓝屏,求大家看看哪的问题
  • ¥60 高价有偿求java辅导。工程量较大,价格你定,联系确定辅导后将采纳你的答案。希望能给出完整详细代码,并能解释回答我关于代码的疑问疑问,代码要求如下,联系我会发文档
  • ¥50 C++五子棋AI程序编写
  • ¥30 求安卓设备利用一个typeC接口,同时实现向pc一边投屏一边上传数据的解决方案。