I seem to have run into a race condition in some formapi code that makes asynchronous server calls. I didn't expect order of execution to matter here, so I'm a little surprised at what's happening. We have a select item on one of our templates that pulls its values from a file. An associated callout can add additional rows to the file, and refresh the select. Since we already had the code to refresh the select written, we use some formapi in the init handler to pre-populate the list rather than coding an inline to do the same thing.
I had to add an additional item that follows the same paradigm. What happens now is that the callback from the asynchronous server call to my formapi never happens. If I flip the order of the calls for the two items, the first one populates and the second doesn't, so it is definitely order dependent (so, really it isn't a true race condition since it's deterministic). I added some debugging to the server call, and verified that the entire thing executes normally. I also added an alert to the callback function in the formapi - it only fires for the second server call, regardless of which it is.
Here is the relevant bit of initialiser code:
// Populate culture from value list, because the api is not so smart, we also
// have to ensure it is present and set the default value.
var cultureObject = IWDatacapture.getItem("/constituent/culture");
var cultureOptions = cultureObject.getOptions();
var c_defaultValue = "";
if ( cultureObject.getValue() != null) {
c_defaultValue = cultureOptions[parseInt( cultureObject.getValue() )].value;
}
populateOptionList("/constituent/culture", "/local/config/****/webform/culture_options", c_defaultValue);
// Populate jobTitle from value list, because the api is not so smart, we also
// have to ensure it is present and set the default value.
var jobTitleObject = IWDatacapture.getItem("/constituent/jobTitle");
var jobTitleOptions = jobTitleObject.getOptions();
var jto_defaultValue = "";
if ( jobTitleObject.getValue() != null) {
jto_defaultValue = jobTitleOptions[parseInt( jobTitleObject.getValue() )].value;
}
populateOptionList("/constituent/jobTitle", "/local/config/****/webform/jobTitle_options", jto_defaultValue);
<snip/>
// Populates an option list using a callout
// xpath of select object, file to populate from relative to $iwhome
function populateOptionList(objectXPath, filePath, defaultValue) {
var params = new Object();
var server = window.location.hostname;
params.workarea = top._dcWin.gWorkarea;
params.objectXPath = objectXPath;
params.filePath = filePath;
params.defaultValue = defaultValue;
//alert the user that an external call is being made.
IWDatacapture.displayMessage("Retrieving values for field...");
top.hiddenFrameRunning = true;
IWDatacapture.callServer("http://" + server + "/iw-bin/webform_callout_populate_select.ipl",params);
}
The net of the server call is that an option list is created, which is happening, and it is sent back to the formapi with an onload event on the body, e.g.
<body onload="parent.getScriptFrame().populateList('$objectXPath',arrOptionList)">
The populateList function actually handles the setting of the options on the item referenced by objectXPath. Any idea why the call to it is getting lost on the whichever server call executes first?
Thanks
Rob