1. #1
    Touch Premium Member pmarko's Avatar
    Join Date
    Dec 2007
    Location
    Ireland
    Posts
    58
    Vote Rating
    1
    pmarko is on a distinguished road

      0  

    Default [FIXED] Ext.Direct does not fire 'xhr' exception

    [FIXED] Ext.Direct does not fire 'xhr' exception


    Hi,
    I was told that this is not a bug, so I ask for help here.
    When I send the request to the server and it is not available I get error instead Transport 'xhr' exception. What's wrong?

    I have created simple page to explain this.

    1.) Btn. 1 click, Echo :: send('FOO') server method is called, server returns FOO - everything is OK. Fig1

    2.) Btn. 2 click, Exception :: makeError() server method is called, server returns SERVER exception, handled by callback - everything is OK.Fig2

    3.) Server is down and any button click (1st or 2nd), firebug reports error. No retries. No exception. Fig3

    4.) Fix apllied. Server down. Any button click. 1st try to connect + 3 retries. 'xhr' or TRANSPORT exception generated, handled by my global exception handler. Fig4

    Question is. Is this a bug or not ???


    HTML Code:
    <html>
    	<head>
    		<link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" />
    		<script type="application/javascript" src="ext/adapter/ext/ext-base.js"></script>
    		<script type="application/javascript" src="ext/ext-all-debug.js"></script>
    		
    		<!-- uncomment this to apply fix -->
    		<!-- <script type="application/javascript" src="js/Ext.direct.RemotingProvider.js"></script> -->
    		
    		<!-- APP API -->
    		<script type="application/javascript" src="remote/api.php"></script>
    	</head>
    	<body>
    		<div>
    			<div id="btn1" style="padding:10px"></div>
    			<div id="btn2" style="padding:10px"></div>
    		</div>
    		<script type="application/javascript">
    PHP Code:
    Ext.onReady(function(){
        
        
    // handle ALL events in Ext.direct
        
    Ext.Direct.on('event',function(e,provider){
            
    console.log('EXT DIRECT GLOBAL EVENT',e);
            
            
    // would be nice to have ability to stop event here 
        
    },this);
        
        
    // handle ALL exceptions in Ext.direct
        
    Ext.Direct.on('exception',function(e){
            
    console.log('EXT DIRECT GLOBAL EXCEPTION',e);
            
    // here is good place for transport exception handling
            
    if (e.type === 'xhr'){     // <-- filter transport exceptions only : type = xhr
                                    // this is NOT a server exception !
                
    Ext.MessageBox.alert('ERROR'e.message );
                
    // or window.location = 'http://anotherserver/unavailable.html'
                // or lock screen, start server availability test every couple seconds 
                // and just wait till server come up again (automated systems)
                
                // would be nice to have ability to stop exception here
                // something like e.stopException() 
            

            
        },
    this);
        
        
    // just test if retry works and url override for simulate transport error
        
    Ext.apply(Ext.app.REMOTING_API,{
            
    /*url : 'remote/foo.php',*/ // <--uncomment this to simulate transport error, 
                                        // or just turn your server off without page refresh of course
            
    maxRetries // <--- retry count if request fails
        
    });
        
        
    Ext.Direct.addProvider(Ext.app.REMOTING_API);
                                        
        new 
    Ext.Button({
            
    text         'ASK SERVER TO DO SOMETHING',
            
    width        100,
            
    renderTo     'btn1',
            
    handler        btnClick
        
    });
        
        new 
    Ext.Button({
            
    text         'ASK SERVER TO FIRE SERVER EXCEPTION',
            
    width        100,
            
    renderTo     'btn2',
            
    handler        btn2Click
        
    });
        
        function 
    btnClick(b,e){
                                
            
    // Action/Class:Echo, method:send
            
    Ext.app.Echo.send('FOO',function(result,e){
                
    // everything is OK.
                
    if(e.status === true){
                    
    console.log('HEY, WELL DONE');
                    
    Ext.MessageBox.alert('WELL DONE','Data form server. "' e.result +'"');
                }else{
                    
    // handle server exceptions generated by server side only
                    // it means we have got server response but error occurred
                    
                    // I don't want to worry about TRANSPORT='xhr' exceptions here
                    
    if (e.type === 'exception'){ // <-- server side exception only : type = exception
                        
    Ext.MessageBox.alert('ERROR','Ooops.. something wrong. "' e.message +'"');
                        
    // e.message could be something like 'sorry, can't save data...'
                        
                        // user action related exception code
                    

                    
    // exception handling code (rollback, cancel, whatever ...)
                
    }
                
            });
        }
        
        function 
    btn2Click(b,e){                
            
    // Action/Class echo, Method:makeError 
            
    Ext.app.Exception.makeError(function(result,e){
                
    // everything is OK.
                
    if(e.status === true){
                    
    console.log('HEY, WELL DONE');
                    
    Ext.MessageBox.alert('WELL DONE','Data form server. "' e.result +'"');
                }else{
                    
    // handle server exceptions generated by server side only
                    // it means we have got server response but error occurred
                    
                    // I don't want to worry about TRANSPORT='xhr' exceptions here
                    
                    
    if (e.type === 'exception'){ // <-- server side exception : type = exception
                        // show message to user or ask him for any action
                        
    Ext.MessageBox.alert('ERROR','Ooops.. something wrong. "' e.message +'"');
                        
    // e.message could be something like 'sorry, can't save data...'
                        
                        // user action related exception code
                    
    }
                     
                    
    // exception handling code (rollback, cancel, whatever ...)
                
    }
                
            });
        }
        
    }); 
    HTML Code:
    		</script>
    		
    	</body>
    </html>
    Fix.
    Code:
    Ext.override(Ext.direct.RemotingProvider, {
    	
    	doSend : function(data){
            var o = {
                url: this.url,
                callback: this.onData,
                ts : this.callBuffer,
                scope: this
            };
    
            // send only needed data
            var callData;
            if(Ext.isArray(data)){
                callData = [];
                for(var i = 0, len = data.length; i < len; i++){
                    callData.push(this.getCallData(data[i]));
                }
            }else{
                callData = this.getCallData(data);
            }
    
            if(this.enableUrlEncode){
                var params = {};
                params[typeof this.enableUrlEncode == 'string' ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
                o.params = params;
            }else{
                o.jsonData = callData;
            }
            Ext.Ajax.request(o);
        }
    	
    });
    api.php
    Code:
    Ext.ns('Ext.app'); Ext.app.REMOTING_API = {"url":"remote\/router.php","type":"remoting","actions":{"Echo":[{"name":"send","len":1}],"Exception":[{"name":"makeError","len":0}],"Time":[{"name":"get","len":0}],"File":[{"name":"list","len":1,"serverMethod":"listFiles"},{"name":"add","len":2,"formHandler":true}]},"namespace":"Ext.app"};
    I'm using php stack provided in your stacks package.

    And one more thing.
    would be nice to have ability to stop exception and event in Ext.Direct

    Thank you.
    Attached Images

  2. #2
    Sencha - Architect Dev Team aconran's Avatar
    Join Date
    Mar 2007
    Posts
    9,365
    Vote Rating
    128
    aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold aconran is a splendid one to behold

      0  

    Default


    pmarko -

    I've taken another look at your report and there is indeed a bug here in Ext.Direct's RemotingProvider. I have committed the fix to SVN. In the mean time you can use the following override:

    Code:
    Ext.direct.RemotingProvider.override({
    
        onData: function(opt, success, xhr){
    
            if(success){
    
                var events = this.getEvents(xhr);
    
                for(var i = 0, len = events.length; i < len; i++){
    
                    var e = events[i];
    
                    var t = e.getTransaction();
    
                    this.fireEvent('data', this, e);
    
                    if(t){
    
                        this.doCallback(t, e, true);
    
                        Ext.Direct.removeTransaction(t);
    
                    }
    
                }
    
            }else{
    
                var ts = [].concat(opt.ts);
    
                for(var i = 0, len = ts.length; i < len; i++){
    
                    var t = this.getTransaction(ts[i]);
    
                    if(t && t.retryCount < this.maxRetries){
    
                        t.retry();
    
                    }else{
    
                        var e = new Ext.Direct.ExceptionEvent({
    
                            data: e,
    
                            transaction: t,
    
                            code: Ext.Direct.exceptions.TRANSPORT,
    
                            message: 'Unable to connect to the server.',
    
                            xhr: xhr
    
                        });
    
                        this.fireEvent('data', this, e);
    
                        if(t){
    
                            this.doCallback(t, e, false);
    
                            Ext.Direct.removeTransaction(t);
    
                        }
    
                    }
    
                }
    
            }
    
        }        
    
    });
    Aaron Conran
    @aconran
    Sencha Architect Development Team

Thread Participants: 1