Atlas enabled web services are fantastic. They provide a rich, wrapped capability that abstracts a lot of the nitty gritty xmlHttp details away from the programmer.
The normal pattern of using Atlas Web Services is a static method call that contains a callBack delegate. Once the method is complete, the callback function is automatically executed. For the most part, the code looks like the following:
function startWebService() {
AtlasWebService.Geography.GetCities (CountryId, onCallback, onTimeout);
}
function onCallBack (results) {
// do something with the results.
}
function onTimeout (results) {
alert (“call Timed out”);
}
Here I'm executing the GetCities web service method passing in the CountryId as the parameter and registering the onCallback method as the onMethodComplete handler and the onTimeout method as the onMethodTimeout handler.
For simple situations this works great, but in a project a while back we needed to pass some context from the caller (startWebService) to the callback (onCallBack). Using the version of the web service calling pattern that I've demonstrated above, this isn’t possible. A thought we had to solve this problem was to wrap the function calls inside of a closure and use private members of the closure to hold state. Something like this:
myClass = function () {
_currCountryId= '';
this.startWebService = function (CountryId) {
_currCountryId= CountryId
AtlasWebService.Geography.GetCities(_currCountryId, onCallback, onTimeout);
}
function onCallback (results) {
alert (_currCountryId);
// handle the results as needed.
}
}
While this looks like it might work from initial glance (besides the race condition that might be present if more than one call to startWebService occurred before the first one completed), we found that _currCountryId wouldn’t be available to the onCallback function. Without jumping into too much JavaScript, the onCallback call is private and therefore unable to access the closure’s member fields (I think that’s the reason at least). Changing the onCallback method to “this.onCallback = function (results)” didn’t work either.
It turns out we were thinking too hard and not reading enough documentation. Atlas’ web service pattern provides a pass-through capability out of the box by using the alternative syntax and the userContext property. The Atlas documentation’s alternative syntax can be found here and the example reads:
requestSimpleService = Quickstart.Samples.SimpleService.EchoString(
document.getElementById('inputName').value , // First webservice parameter
secondParameter, // Second webservice parameter
{
onMethodComplete:OnComplete,
onMethodTimeout:OnTimeout,
onMethodError:OnError,
onMethodAborted:OnAborted,
userContext: "OnbuttonGo_click",
timeoutInterval: 10000
}
);
The blurb below it reads: “The userContext parameter can contain any value (string, number, array, dictionary, or object) and is used to pass contextual information that can be retrieved inside of handlers for errors or time-outs.”
In this example they are passing “OnbuttonGo_click” as the user context. They state the “contextual information that can be retrieved inside of handlers for errors or time-outs,” but it can also be used in the normal callback handler and anything that can be successfully serialized into JSON can be passed.
Let’s take a look at our example using the alternative syntax.
function startWebService(CountryId) {
AtlasWebService.Geography.GetCities (CountryId,
{
onMethodComplete: onCallBack,
onMethodTimeout: onTimeout,
userContext:CountryId }
);
}
function onCallBack (results, response, userContext) {
alert (userContext); // will popup the countryId of before.
}
function onTimeout (results, response, userContext) {
alert (“call Timed out for: ” + userContext);
}
Now, when the web service method returns, the onCallBack function will have both the results as well as the userContext I assigned to the method call in startWebService method.
A couple of things to note:
-
I didn’t include the full alternative call syntax. Since it’s a named parameterized list of properties, it isn’t required that all of them be included.
-
The onCallBack method signature now has 3 parameters. Results, response, and userContext.
By using the userContext property of the alternative syntax I can pass extra data from my caller to my callback. This is pretty darn helpful.
Happy Coding, Joel