I just started working with an open source flash project and ran into an interesting problem. There were two code paths available for loading data. One path was to use a URL and the other was a JavaScript function.
I decided to use the JavaScript function because it provides a clean way to load data without another data shoveling page. It’s a little untraditional but I like JavaScript. Everything worked great as the API is very clean. Unfortunately, when the flash rendered it was slightly different when using the JavaScript loading function.
- loaded via JavaScript Function Example – https://jasonrowe.com/ofc/test.html
- load via URL Example – https://jasonrowe.com/ofc/test.html?ofc=data.html
I posted examples in the project forum but it’s down right now. So I’m putting my thoughts here before I forget.
The root cause of the problem is the application assumes both data loading methods are asynchronous. The application fired off a request to get data and then did some layout initialization via a functioned named “this.set_the_stage();”. It turns out retrieving data via a JavaScript function from flash is synchronous. Thus the layout initialization happened after the flash chart rendered cutting off the y-axis.
This could happen in any language that supports async calls. It’s a good reminder to double check your code paths closely if mixing async and sync. Also, put your initialization code in the instance class constructor or right at the entry point of the program.
So to recap when getting data via a file you can use the async URLLoader.
private function load_external_file( file:String ):void { this.URL = file; // // LOAD THE DATA // var loader:URLLoader = new URLLoader(); loader.addEventListener( IOErrorEvent.IO_ERROR, this.ioError ); loader.addEventListener( Event.COMPLETE, xmlLoaded ); var request:URLRequest = new URLRequest(file); loader.load(request); }
When loading via a JavaScript function the synchronous ExternalInterface.call is available.
if (ExternalInterface.available) return ExternalInterface.call(functionName, optionalArgs);
As a quick test I did something like this and the project ran without layout problems.
//Hack to make fake async call setTimeout(this.parse_json,0,json_string )
The setTimeout hack allows the code to skip over the function and do the initialization.
What I finally ended up doing in the main.as is moving this.set_the_stage() function above the this.find_data(). This way, the initialization in set_the_stage() is called first and all is well.
Here is an example of how to move the function:
public function main() { this.chart_parameters = LoaderInfo(this.loaderInfo).parameters; if( this.chart_parameters['loading'] == null ) this.chart_parameters['loading'] = 'Loading data...'; var l:Loading = new Loading(this.chart_parameters['loading']); this.addChild( l ); this.build_right_click_menu(); this.ok = false; this.set_the_stage();//THIS WAS MOVED HERE if( !this.find_data() ) { // no data found -- debug mode? try { var file:String = "../../data-files/y-axis-auto-steps.txt"; this.load_external_file( file );
Leave a Reply