This is such a weird problem because it intermittently affects random jpegs. One time, an image loads just fine and dandy, the next it time it fails. No errors on the server logs and the images are accessible via a web browser!!!
Weird. :yikes:
Printable View
This is such a weird problem because it intermittently affects random jpegs. One time, an image loads just fine and dandy, the next it time it fails. No errors on the server logs and the images are accessible via a web browser!!!
Weird. :yikes:
For reference, here's the code that loads the images:
MovieController.prototype.loadLargeImage = function(url) {
// check to see if image is already loaded
var id = url.replace('/', '_');
var mcLargeImages = _root.imageMenu_mc.mcLargeImages;
if (
mcLargeImages[id] &&
mcLargeImages[id].getBytesLoaded() == mcLargeImages[id].getBytesTotal()
) {
return false;
}
var src = this._menuitems[url].value;
var mcLarge = mcLargeImages.createEmptyMovieClip(id, mcLargeImages.getNextHighestDepth());
mcLarge.loadMovie(this._siteprefix+src);
mcLarge.url = this._siteprefix+src;
return mcLarge;
}
So, I'm basically creating an empty clip in _root.imageMenu_mc.mcLargeImages and loading the image there.
At this point, _root.imageMenu_mc has _visible = false;
The movie then waits in a preloader until all of the images have loaded / failed before showing the _root.imageMenu_mc movie.
Not sure if the _root.imageMenu_mc movie is playing while the images are loading. It *should* be at gotoAndStop(1);
Would this cause an issue if it was playing?
try using movieClipLoader instead of loadMovie it has an event called onLoadInit that will wait for the jpeg to be loaded before it loads it into the movieclip
Will let you know how I get on with this.
Any ideas why the XML is doing the same thing?
Thanks for your help so far!!! :)
I think that the code that trys to reload on fail is unecessary...don't remove it just comment it out and see if your xml starts behaving better.
Unfortunately, using MovieClipLoader makes no difference - I ruled this out 'case I thought the MovieClipLoader was just a nice way of attaching events to the Movie, rather than loading the movie differently.
My app. *definitely* waits in the preloader until it displays any of the movies being loaded - though they are loaded in place. You can see the preloader counting while the "Error loading URL" messages appear.
The only other way I can think of making this a little more robust is to create a load queue which will load and wait for each clip one at a time, rather than the current approach of just letting flash get on with it.
What do you think there is any merit in trying this approach?
(or am I wasting my time?)
P.S. Removing the retry on the XML just makes that application hang.
wait a second....what is your preloader doing??? i think you have a preloader problem....you do have export for 1st frame unchecked in every object in the library right? and you do have the preloader content and actionscript on frame 1 ......no content or actionscript on frame 2 and then the loaded jpegs and all other content and actionscript on frame 3 or higher......or don't you ? ...are you familiar with how a preloader works or are you trying to use a preloader for your images because if you are trying to use a preloader for just images then you are in my opnion wasteing your time a preloader is used to just preload a large .swf not really individual movie clips jpeg containers or anything else.
i also think you need to thourghly make sure all your xml code is loading and parsing the xml correctly just .....make it load the xml and put the " string paths" to the image in a dynamic text box and make sure it is loading all of the correct string paths and that all the paths its loading are valid then have it load 1 image at a time via a btn press make btn presses the event that causes each image to load for now if it loads all the pictures without a problem then you will know that it cannot process and load all those images that fast if that is the case then i would use setInterval to cause the function that loads the pictures and parses the xml to only fire every few seconds or something along those lines....flash requires at least 2 things to work an event and a function that responds to the event....some people just use the movie loading as the event that fires all their code at 1 time and exspect everything to magically work within the 3 trillionths of a second that it takes for all the code to fire....see what i mean? flash files don't load slowly because the code takes along time to execute flash files load slowly because of the images and user interface objects having to be processed actionscript alone is stupid fast.
Wow calmchess! Your leaving no stone unturned.
I've been programming a while but this is only my second decent flash project, so, as I've said you help is really appreciated.
I've got two "preloaders". The first is for the main movie which does as you say.
Frame 1:
update a big text field with a percentage
until done (then gotoAndPlay(3)
frame 2:
gotoAndPlay(1)
frame 3:
rest of movie
The movie seems to load okay i.e. all movies loaded and objects created properly.
When it gets to the end of loading, it hands over control to the MovieController object (the code that I attached to a previous posting).
At this point, a second "preloader" is responsible for waiting for dynamic resources (i.e. the images and xml I mentioned) in response to the user's clicks, etc.
This is a movie in the main movie which shown a percentage done and the calls MovieController.pollSectionPreloader(). This function goes through an array of objects monitoring getBytesLoaded() vs getBytesTotal().
The pollSectionPreloader works in stages:
1. wait for resources to load e.g. images, xml, etc
2. wait for new movie clips to be constructed using those resources
3. finally show the new movie clips
For example:
ACTION PHASE:
1. user click "news", the MovieController.gotoPage('News') is called.
2. close all open "windows", empty preloader
LOAD PHASE:
3. call fetchDataObject('News/Article') which creates and XML object, calls load and pushes the XML object into the preloader array.
4. preloader movieclip is opened and plays, repeated calling the pollSectionPreloader() function
5. pollSectionPreloader updates percent done and issues any retries
BUILD PHASE:
6. when done, preloader moves to "stage 2", which calls buildNewsPage()
7. in this instance, it sets-up an existing movie clip with new html TextField containing the article
DISPLAY PHASE:
8. when this is done, the pollSectionPreloader finally displays and gotoAndPlay's the news movie clip
Basically: I tried *really* hard to make sure the images/xml really were loaded before doing anything with them!
Of course, they've got to be loaded somewhere, so I'm loading them into _root.imageMenu_mc.mcLargeImages using createEmptyMovieClip and loadMovie.
The parent movie (_root.imageMenu_mc) is on the stage but is _visible = false and gotoAndStop(1).
Should I be loading the images anywhere else? or is this okay?
Regarding to you're using actionscript "stupid fast" comment, as you can see from above, I've tried v. hard to take time loading though the instructions to do the loading do come all at once and right at the beginning.
So, I guess the idea of a load queue (that I mentioned above), seems like the only option left to try?
Will give it a go and let you know how I get on.
Oh, and XML paths are okay 'cause:
1. check the XML in a browser
2. ran lots of trace over this code in the past
3. the retries actually work!
well hey i didn't say all my critisim is correct or even necessary i just try to make posts educational but you are keeping an open mind about everything i have to say and i know you are being subjective....anyway i have another thought on frame 2 you above you have gotoAndPlay(1); I don't use that try commenting out that piece of code and see what happens
Hey, no worries! :)
I'm just glad to have someone help narrow things down - my replies are just to give you (or anyone else reading) as much details as I can, and to let you know I've tried some of the things you suggest.
Re. frame 2 and gotoAndPlay(1): definitely not an issue. The problems occur with the second "dynamic content preloader" not the initial "make sure the movies all here" preloader.
Cheers!
following the problem description it sounds very much that what calmchess said might be the problem.Quote:
Originally Posted by calmchess
i once made an app that had to load quite a couple of xml files successively, and came up with all kinds of weird problems, some of which sound very much like the ones looksystems describes.
what i did was: i wrote loader classes for the xml files. these classes would load one xml file at a time, parse it, do all kinds of other things i needed them to do and then fired an event (using EventDispatcher) to signal: "hey, you can load the next xml file." that did the trick for me and taught me that loading several files has to be controlled in one way or another.
as i said, i used custom events, but i also found a load queue manager (http://blog.bittube.com/assets/downl...Manager.as.zip) which i haven't played around with yet, but maybe it's of use to you...
theTick:
I agree "loading too many things at once" seems the most likely candidate, since calmchess has kindly help me discount most of the other possibilities.
Will report back when I've adapted my "preloader" to work as load queue rather than just waiting and monitoring the list of already loading movie clips, et al.
Hopefully, loading serially won't slow things down too much.
Cheers.
theTick:
will take a look at the load queue manager also, thanks.
A couple more links here:
http://www.actionscriptclasses.com/c...viecliploader/
http://www.justgooddesign.com/blog/d...g-in-flash.htm
Interesting description of one loader on Actionscript Classes:
LoadingQueue is a simple loading proxy function that controls queuing of loading actions, so you can better control what gets loaded, when, in what order, without being forced to call a bunch of loads and pray that they don’t timeout in case there are too many files to load.
Sounds just like the my problem! :(
Okay so I think I've *finally* resolved the problem (works in the test environment, but still subject to more QA).
Having said that, I'm really surprised that the final solution has had to jump through so many hoops - but then I'm not a seasoned actionscript programmer so I'm could be missing a trick?
Basically, I implemented my own load queue - rather than firing off a load requests and trying to catch the errors. The queue uses XML.load or MovieClipLoader.loadClip to start the process and traps onLoad(success) for the XML and onLoadComplete and onLoadError for the MovieClipLoader.
Each of these listeners sets a "loaded" or "failed" flag.
The load queue initiates a load then waits for the loaded or failed state - when a fail comes in, it issues a retry.
This worked fine in the development enviroment but testing "in browser" resulted in some clips not completing but, rather, they would just sit there with 0 getBytesTotal().
To overcome this problem, I used getTimer() to record the time the load was initiated and marked the object as "failed" if it took longer that 100 milliseconds to return getBytesTotal() > 0 (this is only for non XML clips).
Finally, because loading the items sequentially was ultra reliable but far too slow, I modified the load queue to initiate N requests and wait for the results where N is around 3 to 5 requests and throttled this back to 1 request for clips that failed to load. Failures would be put back onto the load queue (where they would be retried after the current round of requests had been finished).
In short: I've got a solution that works, maybe one of the many LoadQueue classes I mentioned above would also solve the problem, BUT I can't help but feel that this should be better handled by a core library component.
Or maybe I'm just missing something obvious?
Anyway a big thank you to everyone who offered up ideas and help... It meant I could focus on the real problem much quicker as I was much more confident that I wasn't doing something really dumb!
Cheers everyone! :)
Here's some code... just in case it's of help to anyone:
Code:// LOAD QUEUE
MovieController.prototype.fetchXml = function(url) {
if (this._content[url]) return;
var xml = new XML();
xml.url = url;
xml.target = xml;
xml.onLoad = function(success) {
if (!success) this.failed = true;
else {
this.caller.onDataXml(this);
this.loaded = true;
}
}
this.addLoadQueue('xml', xml);
}
MovieController.prototype.fetchImage = function(clip, url) {
var loader = new MovieClipLoader();
loader.url = url;
loader.target = clip;
loader.onLoadComplete = function() {
this.loaded = true;
}
loader.onLoadError = function() {
this.failed = true;
}
this.addLoadQueue('loader', loader);
}
MovieController.prototype.addLoadQueue = function(type, obj) {
obj.type = type;
obj.loaded = false;
obj.failed = false;
obj.caller = this;
obj.retries = 0;
this._preload.push(obj);
}
MovieController.prototype.processLoadQueue = function() {
var debug = false;
var unknown = 32768;
var total = 0;
var loaded = 0;
for (var c in this._preload_current) {
var current = this._preload_current[c];
if (typeof current != 'object') continue;
var l, t, p;
switch (current.type) {
case 'loader':
p = current.getProgress(current.target);
case 'clip':
if (p == undefined) p = current.target;
t = p.getBytesTotal();
l = p.getBytesLoaded();
if (t < 0) current.failed = true;
else if (t > 0) {
if (t == l) current.loaded = true;
break;
} else {
if (current.init + 100 < getTimer()) current.failed = true;
}
case 'xml':
t = unknown;
l = (current.loaded) ? unknown : 0;
break;
default:
current.failed = true;
}
if (debug) this.showTrace(current.url+' '+l+'/'+t+' '+current.loaded+' '+current.failed, 1);
if (debug) trace("STATE: "+current.url+' '+l+'/'+t);
if (current.failed) {
if (current.retries < 5) {
++current.retries;
if (this._debug) trace('RETRY('+current.retries+'): '+current.url);
this._preload.push(current);
} else {
if (this._debug) trace('FAILED: '+current.url);
}
this._preload_delta -= (this._preload_delta / this._preload_current.length);
this._preload_current[c] = false;
continue;
}
if (current.loaded) {
if (debug) trace('DONE: '+current.url);
this._preload_current[c] = false;
}
loaded += l;
total += t;
}
if (debug) this.showTrace(this._preload_current.length+'/'+this._preload.length+' '+loaded+'/'+total);
if (total && loaded < total) return (100.0 * loaded / total);
if (!this._preload.length) {
this._preload_current = new Array();
this._preload_percent = 100;
this._preload_delta = 0;
return 100;
}
this._preload_percent += this._preload_delta;
var delta = (100.0 - this._preload_percent) / this._preload.length;
var c = 0;
this._preload_current = new Array();
this._preload_delta = 0.0;
while (this._preload.length && this._preload_current.length < 4) {
var current = this._preload.pop();
if (debug) trace('LOAD: '+current.url);
switch (current.type) {
case 'xml':
current.target.load(this._siteprefix+'FlashTalk/'+current.url);
break;
case 'loader':
current.loadClip(this._siteprefix+current.url, current.target);
break;
case 'clip':
default:
current.type = 'clip';
current.target.loadMovie(this._siteprefix+current.url);
break;
}
current.init = getTimer();
current.failed = false;
this._preload_current.push(current);
this._preload_delta += delta;
if (current.retries) break;
}
return 0.0;
}
// SIMPLE "IN MOVIE" TRACE FUNCTION
MovieController.prototype.showTrace = function(message, level) {
if (!level) level = 0;
_root.createTextField("trace"+level,1000+level,0,level*10,0,0);
_root['trace'+level].autoSize = true;
_root['trace'+level].text = message;
}