Update: somehow this works when running flash in browser, but doesn't work if you run from IDE. You might want to try running in browser if you have the same problem.
I am making a chat application that repeatedly reads a text file from my server using Flash & Actionscript 3.0. I am opening the file with URLLoader, and it works fine at first. However after around 10 calls, the URLLoader gets stuck.
It does not give a completion event, does not give a security error, does not give a status event and does not throw an exception. It simply never fires any event at all. I even added a random value to the URL to make sure it is not some caching issue. I can detect when it gets stuck of course, but there doesn't seem to be any way to unstuck it. Even if I call close() on the URLLoader and then set it to null and create another one, it won't resume polling.
Below is the function that polls the server and gets called once every two seconds.
private function check_server() {
var url:String = "http://coworkthailand.com/say/snd/index.php?"+Math.random();
if (loader != null) {
trace("was already checking "+loader.bytesLoaded+" / "+loader.bytesTotal);
return;
}
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, completeHandler);
loader.addEventListener(flash.events.IOErrorEvent.IO_ERROR,
function(e:Event) { loader = null; trace("fail"); })
loader.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR,
function(e:Event) { loader = null; trace("security error"); })
loader.addEventListener(flash.events.HTTPStatusEvent.HTTP_STATUS,
function(e:flash.events.HTTPStatusEvent) { trace("status "+e.status); });
try {
loader.load(new URLRequest(url));
} catch (error:Error) {
trace("Unable to load requested document.");
}
}
This is not an important project, but any ideas would be much appreciated!
For this scenario, best practice dictates using a single instance of URLLoader; chances are you're getting blocked somewhere by competing calls. As well, you might try using a simple flag to detect whether your loader's busy on an existing call before making another one; here's a working example using a single loader making requests every five seconds, showing both the single loader and the "isOpen" check:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="app_init()">
<mx:Script>
<![CDATA[
private var timer:Timer;
private var loader:URLLoader;
private var isOpen:Boolean;
private function app_init():void
{
timer = new Timer(5000)
timer.addEventListener(TimerEvent.TIMER, timer_tick, false, 0, true)
loader = new URLLoader();
loader.addEventListener(Event.OPEN, loader_open);
loader.addEventListener(Event.COMPLETE, loader_complete);
// Start the timer
timer.start();
}
private function timer_tick(event:TimerEvent):void
{
// Check if the loader's busy before calling load, and/or close()
if (!isOpen)
{
// loader.close();
loader.load(new URLRequest("http://mydomain.com/myfile.txt"));
}
}
private function loader_open(event:Event):void
{
// Mark as open
isOpen = true;
}
private function loader_complete(event:Event):void
{
// Do work
// Mark as closed
isOpen = false;
}
]]>
</mx:Script>
</mx:Application>
Hope it helps! Good luck.
It's also possible that your object is being cleaned up by the GC due to them not being connected to the main object graph.
It's also worth checking your HTTP traffic using Fiddler or Charles, it might help you get a better idea of what is going on.
A browser usually allows only 2 simultaneous HTTP KeepAlive connections. The other connections are postponed.
I'm just guessing here, but perhaps the Flash Engine is blocked by the various parallel URLLoader
s (if for some reason one gets stuck for a little bit more than two seconds, you already have two, etc.)
My idea is: use a single URLLoader
. Set up the callbacks and event hooks in an init()
function, and call load()
, and reuse the same instance every time you check the server for changes. That way, when the URLLoader
is still busy, the new load request will either be ignored or it will cancel the previous one (not sure which).