我正在使用html5 filereader API在本地获取照片,而无需用户上传照片。

在支持它的浏览器中,我允许多个选择,因此我遍历所选文件并在每个文件上执行一项功能(TC.editor.renderSlide()),如下所示:

 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);
    }
},

问题在于TC.editor.renderSlide()函数可能要花费大量时间来执行(执行 Canvas 和DOM操作),因此当处理8个左右的大型图像文件时,浏览器将锁定相当长的时间。在此期间,即使“处理gif”也停止了动画处理。

有什么方法可以确保每个reader.onload事件仅在前一个事件完成后才触发?这样,通过分别查看每次对TC.editor.renderSlide()的调用结果(而不是在处理所有内容时锁定浏览器的当前状态),可以为用户提供定期的进度更新

我尝试将简单的setTimeout添加到renderSlide()无济于事?

任何帮助或想法将不胜感激。

最佳答案

onload事件按顺序触发,当前未处理另一个处理程序时不执行该处理程序(“JS是单线程”)。当您在处理程序中启动某些异步处理(超时,动画,文件加载)时,这当然不算在内。

在这种情况下,您将需要手动处理顺序处理。使用队列等待过程很容易,这些队列在一个完成时执行:

var waiting = [];
// …create many parallel loaders, and on each:
    ….onevent = execute;

function execute(e) {
    if (waiting.active)
        waiting.push(e);
    else {
        waiting.active = true
        // do something that takes its time, supplying a
          … function callback(ready) {
            waiting.active = false;
            if (waiting.length)
                execute(waiting.shift()); // go on with next
          }
    }
}

但是,在我看来,不是renderSlide引起了问题,而是您同时实例化了这么多FileReader。通过将for循环变成异步调用的“递归”函数,使它们开始依次加载文件:
var files = […]
(function handle(i) {
     if (i >= files.length) return;
     // create loader
     ….onevent = function(e) {
          // do processing, and then call
          handle(i+1);
          // or call that from another callback if you want to do async
          // processing, like "renderSlide"
     };
})(0);

09-25 16:19