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!

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

报告相同问题?

悬赏问题

  • ¥100 求三轴之间相互配合画圆以及直线的算法
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站