PDA

View Full Version : Custom Ajax proxy + send application wide event on exception



L0L0
15 May 2013, 12:37 PM
Hi,

I am setting up a Chrome / Firefox console like panel to the bottom of my viewport.

In my MVC application I use two way of communication with my server, a custom Ext.data.Connection and a custom proxy that extends Ext.data.proxy.Ajax.

I would like to be able to send an application wide event from the proxy when there is an exception (I'm allready able to do it from the custom Ext.data.Connection).

Here is the proxy code:

Ext.define('MyApp.data.proxy.OData', {
extend: 'Ext.data.proxy.Ajax',
alias: 'proxy.odata',

pageParam: undefined,
startParam: '$skip',
limitParam: '$top',
sortParam: '$orderby',

requires: [
'Ext.data.reader.Json',
'Ext.data.writer.Json' ],

listeners: {
exception: function(proxy, response, operation, eOpts){
//Tried the following but application is not reachable
this.application.fireEvent('odataexception', proxy, response, operation, eOpts);
}
},...


This proxy is used in differents models like this one:


Ext.define('MyApp.model.Resource', {
extend: 'Ext.data.Model',

requires: [
'MyApp.data.proxy.OData'
],

fields:[{
name: 'id', type: 'int'
}, {
name: 'name', type: 'string'
}, {
name: 'canLogin', type: 'boolean'
}],

proxy: {
type: 'odata',
url : MyApp.Config.baseUrl + 'Resources',
writer: {
writeAllFields: true
}
}
});

And in my error handler controller I catch the event like that:


//Register to application global events
//sent by MyApp.data.Ajax or MyApp.data.proxy.OData requests
this.application.on({
communicationerror: this.onCommunicationError,
scope: this }
);


Do you have any idea on how I can send an event from within my proxy class to my error controller (that has no links at all with the proxy)?

I have been searching for hints on google and on the forum but I'm still blocked.

Thanks for your help.

hendricd
16 May 2013, 7:11 AM
@LOLO:

Your approach might be a bit over-engineered. Simplify by targeting one of the base proxy classes and route your exceptions through something native to all Controllers (any component):




Ext.define('MyApp.data.ExceptionHooks', {
override : 'Ext.data.proxy.Server',
require : ['Ext.data.proxy.Server'],

setException: function(operation, response) {
this.callOverridden(arguments);
var router = this.getEventRouter();
router.fireEvent('exception', this, operation, response );

},
getEventRouter : function() {
return this.exceptionRouter ||
(this.exceptionRouter = new Ext.Component({exceptionHook : true});
//Application bus is only bound (listens) for Component classes !!
}
});

//Now, a single controller to manage them all:

Ext.define('MyApp.controller.ProxyException', {
extend : 'Ext.app.Controller',

init : function(app) {
this.control( {
'component[exceptionHook]' : {
exception : this.onProxyException
}
});

},

onProxyException : function(proxy, operation, response) {

}

});


This strategy would replace the need to subclass each of your proxies, and ANY proxy that threw an exception would be handled centrally.

Tweak it. ;)

L0L0
21 May 2013, 4:00 AM
@hendricd

Sorry for the delay in my answer I-|

Thanks for your prompt reply.
I'll definitly give a try to your solution, it looks like a very good idea.

On my side I have been implementing a Singleton MessageBus that wil be used in other parts of the software:



Ext.define('MyApp.tools.GlobalEventManager', { extend: 'Ext.util.Observable',
singleton: true,

appRef: null,

/**
* Initialise the GlobalEventManager singleton setting the
* reference appRef to the application
* This reference will be used to fire / register to event
* @param {Object} application - the application to reference
*/
initComponent: function(application){
this.appRef = application;
},

/**
* Fires a global event.
* Override the parent Ext.util.Observable.fireEvent method
* @param {String} eventName the name of the event to send
* @param {Object...} args Variable number of parameters are passed to handlers
*/
fireEvent: function(eventName) {
this.appRef.fireEvent(eventName, Ext.Array.slice(arguments, 1));
},

/**
* Register a global event.
* Override the parent Ext.util.Observable.addListener method ('on' is an alias)
* @param {String} ename The name of the event to listen for. May also be an object who's property names are
* event names.
* @param {Function} fn The method the event invokes. Will be called with arguments given to
* {@link #fireEvent} plus the `options` parameter described below.
* @param {Object} [scope] The scope (`this` reference) in which the handler function is executed. **If
* omitted, defaults to the object which fired the event.**
* @param {Object} [options] An object containing handler configuration.
*/
on: function(ename, fn, scope, options) {
this.appRef.on(ename, fn, scope, options);
}

And I pass the application reference to it:

//Initialize the global event manager
MyApp.tools.GlobalEventManager.initComponent(this.application);

It allow me to solve my issue and to anticipate future needs, but your solution seems much more structured.

Thanks for your help :)