I have an upload module that loads a lot of files into memory (no actual uploading) and process them using a memory-intensive function. For ~300Mb of files, it will take the processing function approximately 5 seconds to finish.
My processing function has a progress callback which is called at every slice processed, with a floating-point progress indicator as argument. The (simplified) vue.js component looks like this:
Template (HTML):
<div class="progress" v-bind:style="{ width: progress + '%' }"></div>
Script (ES6):
export default {
name: 'Dropzone',
data () {
return {
progress: 0
}
},
methods: {
onDrop (e) {
let $vm = this;
let files = e.target.files;
loadFunction(files, function progressCb (progress) {
// This lags
$vm.progress = Math.round(progress * 100);
// also tried explicit data setting:
// $vm.$set('progress', Math.round(progress * 100));
// also tried manual updating:
// document.querySelector('.progress').style.width = Math.round(progress * 100) + '%';
// or: $('.progress').css('width', Math.round(progress * 100) + '%');
// But this works without lag:
window.document.title = Math.round(progress * 100);
}, function doneCb () {
alert('done');
});
}
}
}
The window.document.title
updating goes smoothly, linearly from 0 to 100%, whereas the progress bar's behavior is erratic, sometimes advancing by steps of 27%, sometimes going straight from 0% to 100% after 5 seconds of waiting.
My understanding of the problem is that the DOM updates are being throttled by Vue.js' async updates queue due to the high quantity of operations the Javascript VM has to process while updating the progress bar. How do I circumvent this limitation?
loadFunction()
work? Is it truly async? are the individual files processes in individual async calls? I think but can't promise (pun not intended), that it would work if you wrapped each file in an individual Promise, wrapped all of them inPromise.all()
, and increased the progress value in each Promisesthen()
?window.document.title
updating fine when the DOM lags?