Passing extra data to callbacks
It's common to need to pass extra information to a callback method, but since all callback methods have only one parameter (the return code from the remote method) this can be tricky.
The 3.0 release of DWR addresses this problem with the addition of several optional attributes on the call meta-data object: args, callbackArgs, and exceptionArgs. Check the download section for details on the release of 3.0.
For all DWR releases prior to 3.0 the solution is to use a Javascript closure.
DWR 3.0 and later
DWR 3.0 allows for arguments to be specified and passed to handlers -- eliminating the need for JavaScript closures. These arguments can apply to the callbackHandler the exceptionHandler, or both. In order to take advantage of this feature you must use a call meta-data object (Call meta-data is explained in the scripting introduction).
var dataFromBrowser = ...;
var callMetaData = {
callback:callbackFunction,
args: dataFromBrowser // specify an argument to pass to the callback and exceptionHandler
};
Remote.method(params, callMetaData);
function callbackFunction(dataFromServer, arg1) {
// you will now have access to dataFromBrowser as arg1
}
Rules:
- args - If specified will be used as a default argument to pass to the callback and will apply to both callback handlers and exception handlers.
- callbackArgs - If specified will apply to callback handlers and will override args.
- exceptionArgs - If specified will apply to exception handlers and will override args.
var dataFromBrowser = ...;
var dataFromBrowser2 = ...;
var callMetaData = {
callback:callbackFunction,
args: dataFromBrowser, // specify an argument to pass to the exeptionHandler
callbackArgs: dataFromBrowser2, // overrides args will be passed to the callback
exceptionHandler: exceptionHandlerFunction
};
Remote.method(params, callMetaData);
function callbackFunction(dataFromServer, arg1) {
// you will now have access to dataFromBrowser2 as arg1
// callbackArgs overrides args
}
function exceptionHandlerFunction(exceptionMessage, exception, arg1) {
// you will now have access to dataFromBrowser1 as arg1
// args also applies to exceptionHandlers
}
A word about scope
The 3.0 release also addresses scope issues within callback and exception handlers. We have added several optional attributes on the call meta-data object: scope, callbackScope, and exceptionScope.
(function() {
someObject = {};
someObject.privateVar = "Private variable from the main object.";
someObject.callbackFunction = function(dataFromServer) {
alert(this.privateVar);
// The preceding line will alert the value of privateVar.
// The key here is the use of 'this'. The scope is not
// lost because it is specified in the call-meta data object
// and used to execute the callback function.
}
})();
var callMetaData = {
callback:someObject.callbackFunction,
scope: someObject
};
Remote.method(params, callMetaData);
Rules:
- scope - If specified will be used as the default scope and will apply to both callback handlers and exception handlers.
- callbackScope - If specified will apply to callback handlers and will override scope.
- exceptionScope - If specified will apply to exception handlers and will override scope.
Note: The default scope is window.
Before DWR 3.0 - JavaScript Closures
A JavaScript closure is required to pass extra data to a callback or exception handler prior to the 3.0 release. For example, your callback method needs to look something like this:
function callbackFunc(dataFromServer, dataFromBrowser) {
// do something with dataFromServer and dataFromBrowser ...
}
Then you can arrange for this method to be called as follows:
var dataFromBrowser = ...;
// define an erasure function to store a reference to
// dataFromBrowser and to call dataFromServer
var callbackProxy = function(dataFromServer) {
callbackFunc(dataFromServer, dataFromBrowser);
};
var callMetaData = { callback:callbackProxy };
Remote.method(params, callMetaData);
(Call meta-data is explained in the scripting introduction)
In other words the function that you pass as the callback is not the real callback - it's just a closure that acts as a proxy, to pass the data on having added in the client side data.
You could write this more succinctly as:
var dataFromBrowser = ...;
Remote.method(params, {
callback:function(dataFromServer) {
callbackFunc(dataFromServer, dataFromBrowser);
}
});
