I am using the html5 filereader API to get photos locally without the user having to upload them.
In browsers that support it I am allowing multiple selections so I am looping through the selected files and performing a function on each one (TC.editor.renderSlide()) as shown below:
handlePhotoUploads: function(event) {
var self = this;
TC.dialog.destroy();
var files = event.target.files;
var count = files.length + TC.editor.cache.slides.length;
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
var index = TC.editor.getNewSlidesIndex();
TC.editor.addNewSlide('photo', index);
reader.onload = (function(theFile) {
var slideindex = index;
return function(e) {
TC.editor.renderSlide(slideindex, e.target.result, 'internal', count);
};
})(f);
reader.readAsDataURL(f);
}
},
The problem is that the TC.editor.renderSlide() function can take a significant amount of time to perform (performs canvas and DOM manipulations) so when dealing with 8 or so large image files the browser gets locked for a substantial amount of time. Even the ‘processing gif’s stop animating during this period.
Is there any way to ensure that each reader.onload event fires only after the previous one has completed? This way the user would be given regular progress updates by seeing the result of each call to TC.editor.renderSlide() individually rather than the current situation which locks the browser while everything is being processed?
I have tried adding a simple setTimeout to renderSlide() to no avail?
Any help or ideas would be greatly appreciated.
The
onloadevents do fire sequentially, the handler is not executed while an other one is currently processed (“JS is single-threaded”). This of course does not count when you start some asynchronous processing (timeouts, animations, file loads) in a handler.In that case, you will need to manually handle the sequential processing. It’s easy using a queue of waiting processes which are executed when one is finished:
However, it seems to me that not
renderSlideis causing the problems, but that you instantiate so manyFileReaders at the same time. Make them start loading files one after the other, by turning your for-loop into an asynchronously called “recursive” function: