PDA

View Full Version : Thoughts about the 'len' Propertie in Remoting Provider



crp_spaeth
11 May 2009, 8:10 AM
Hi there,

after reading the code of RemoteProvider is stuck at the doCall Method and want to share a few thoughts about the len Parameter.


For those who didn't dive into the code yet the current docall Method:


doCall : function(c, m, args){
var data = null, hs = args[m.len], scope = args[m.len+1];

if(m.len !== 0){
data = args.slice(0, m.len);
}

var t = new Ext.Direct.Transaction({
provider: this,
args: args,
action: c,
method: m.name,
data: data,
cb: scope && typeof hs == 'function' ? hs.createDelegate(scope) : hs
});

if(this.fireEvent('beforecall', this, t) !== false){
Ext.Direct.addTransaction(t);
this.queueTransaction(t);
this.fireEvent('call', this, t);
}
},

What I dont like about the current implementation, that you need to have a length propertie for each RF. While this is useful for many cases there are many cases where some args are optional for example. Okay I could add a null to avoid running into exception but I think it would be much nicer to have something like a minlen, maxlen and the possibility to even not set len at all.

I implemented that and it could look something like that:

doCall : function(c, m, args){
var data = null;

var minLen = m.minLen ? m.minLen : m.len;
var maxLen = m.maxLen ? m.maxLen : m.len;
var argsLen = args.length;
// check last an prelast for function
var cb;

if(argsLen >= 2 && typeof args[argsLen-2] == 'function'){
cb = args[argsLen-2].createDelegate(args[argsLen-1]);
argsLen = argsLen -2;
} else if(argsLen >= 1 && typeof args[argsLen-1] == 'function') {
cb = args[argsLen-2];
argsLen = argsLen -1;
}

if(maxLen && argsLen > maxLen) {
throw("The method: " + m.name + " from action: " + c +" was called with to many Arguments! Maxum Arguments: "+ maxLen+ " Sent arguments: "+argsLen);
}
if(minLen && argsLen > minLen) {
throw("The method: " + m.name + " from action: " + c +" was called with to less Arguments! Minimal Arguments: "+ minLen+ " Sent arguments: "+argsLen);
}

if(argsLen !== 0){
data = args.slice(0, argsLen);
}

var t = new Ext.Direct.Transaction({
provider: this,
args: args,
action: c,
method: m.name,
data: data,
cb: cb
});

if(this.fireEvent('beforecall', this, t) !== false){
Ext.Direct.addTransaction(t);
this.queueTransaction(t);
this.fireEvent('call', this, t);
}
}

What do you think?

TommyMaintz
11 May 2009, 8:58 PM
You can look at the 'len' property as the minLen property. Every extra argument you send will be passed to the serverside method (except for the callback function ofcourse), and can be seen as an optional.

For example in the serverside router code for my PHP implementation I have the following:


if(count($params) < $mconf['len']) {
throw new Exception("Not enough required params specified for method: $method on class $class");
}


For more info about my PHP implementation for Direct look here: http://extjs.com/forum/showthread.php?t=68186

crp_spaeth
13 May 2009, 4:02 AM
I don't agree with that. the curren len Property is not a minimum count of arguments!


Because of the following line in the RemoteProvider will no extra Parameters get send to the server...

data = args.slice(0, m.len);

And that is exactly my point

crp_spaeth
9 Jun 2009, 12:28 PM
I run in this Issue again while i tried to get store for a combobox running.

The Store just didn't get filled with records until I set the len propertie of a function with no parameter to 1.

I think you should really think about my advice again....

gurufaction
15 Jun 2009, 7:23 AM
Did you ever get an official response to your posting? I am running into the same issue.

crp_spaeth
15 Jun 2009, 7:47 AM
sadly not

azbok
16 Jun 2009, 4:20 PM
Thanks for this thread! I don't like the len property either...

What I want is the ability for the javascript side to be able to pass in whatever arguments it wants and not be restricted, you never know when you wanna "break the rules". If the server side wants, it can verify the parameters.

This adjustment just passes all of the arguments up to but not including the last one which is the function callback.



doCall : function( c, m, args ) {

// Make sure a length is always set no matter what!
// The last param is assumed to be a fn callback and everything else is data
m.len = m.len || (args.length - 1);

var hs = args[m.len], scope = args[m.len+1];
var data = args.slice(0, m.len || (args.length - 1));

var t = new Ext.Direct.Transaction({
provider: this,
args: args,
action: c,
method: m.name,
data: data,
cb: scope && typeof hs == 'function' ? hs.createDelegate(scope) : hs
});

if( this.fireEvent('beforecall', this, t) !== false ) {
Ext.Direct.addTransaction(t);
this.queueTransaction(t);
this.fireEvent('call', this, t);
}
}

evant
17 Jun 2009, 2:06 AM
Perhaps we could add support for "variable" function, if no length is defined then it will just send everything. However it's not likely we'll get rid of the length parameter.

azbok
17 Jun 2009, 9:42 AM
Perhaps we could add support for "variable" function, if no length is defined then it will just send everything. However it's not likely we'll get rid of the length parameter.

The question is, what should the default be if no len is specified? For my personal use, I like the convenience of having no len specified to mean "variable" function. In order to determine that for myself, I ask myself, "What would cause the least amount of problems for myself?". My answer is, "If the code *looks* like it's supposed to be doing something, I'd want it to do that". So if you do Remote.MyFunction('a', 'b', 'c', function (result, response) {}), it looks like it should pass in those 3 parameters.

In fact after writing the above, for me, having a length parameter (with the current implementation) would be a hindrance because it hides bugs. You may have the 'a', 'b', 'c' params but with a len:2, it only passes 2 of them and a future maintainer of the code would have absolutely no clue about the extra 'c' param and if it does anything at all.

My vote for ease of use is have a minLen/maxLen/length param only for javascript sanity checking but always pass all of the parameters. The server side should always validate it's parameters anyway and it's up to the server to either throw an exception or just ignore them. The javascript shouldn't "protect" the server from bad stuff.

durlabh
8 Jul 2009, 10:23 AM
With our grids, we have a few plugins and we wanted to post the data only if it is needed. Hence, the number of parameters is dynamic. Since Ext.Direct sends parameters as Hash or Array, I modified the doCall method slightly to serve my purpose:



// Allows to use the dynamic number of parameters
Ext.override(Ext.direct.RemotingProvider, {
doCall: function(c, m, args) {
var mapParameters = m.mapParameters !== false;
if (!mapParameters) {
m.len = args.length - 1;
}
var data = null, hs = args[m.len], scope = args[m.len + 1];

if (m.len !== 0) {
data = args.slice(0, m.len);
}

var t = new Ext.Direct.Transaction({
provider: this,
args: args,
action: c,
method: m.name,
data: data,
cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
});

if (this.fireEvent('beforecall', this, t) !== false) {
Ext.Direct.addTransaction(t);
this.queueTransaction(t);
this.fireEvent('call', this, t);
}
}
});


In my use case, on the server side implementation, instead of having different methods with different signatures, I pass DirectRequest object to each method call. Hence, the number of parameters is fixed and the method itself can handle whatever way it wants to handle the request. This way, signature of Form or non-form methods is same.

- Durlabh