Search code examples
vue.jsdownloadelectronaxiosquasar

Multiple Downloads freezes my app - vuejs, quasar, electron


i have a problem in my App. I am using the following software:

"axios": "^0.16.2",
"axios-retry": "^3.0.1",
"babel-runtime": "^6.25.0",
"lodash": "^4.17.4",
"moment": "^2.19.1",
"node-machine-id": "^1.1.9",
"numeral": "^2.0.6",
"pdfjs-dist": "^2.0.303",
"quasar-extras": "0.x",
"quasar-framework": "^0.14.4",
"vue": "~2.3.4",
"vue-async-computed": "^3.3.1",
"vue-fullscreen": "^2.1.3",
"vue-pdf": "^2.0.4",
"vue-router": "^2.7.0",
"vue-scrollto": "^2.8.0",
"vue-video-player": "^5.0.2",
"vuedraggable": "^2.16.0",
"vuex": "^2.4.1"

My App needs to download files from a server when a user hits the thumbnail. On the first run, the app downloads all the thumbnails. This has a normal speed. 60 GET request are starting at the same time. Now when i want to download a file (which is a pdf with 3mb) the app freezes for 5 to 10 seconds and then it starts the download.

The download will be done with the same function: (file is a full url)

function downloadAndWrite(file) {
  this.$store.dispatch(START_DIMMER, {
    title: this.$t('dimmer.generalSetup.title'),
    description: this.$t('dimmer.generalSetup.description')
  });
  // console.time('fetchFile' + file);
  let responseType = 'arraybuffer';
  if (this.$q.platform.is.cordova) {
    responseType = 'blob';
  }

  return this.$http
    .get(`${file}`, {
      timeout: 1800000, // 30 minutes for large files
      responseType: responseType
    })
    .then((response) => {
      return this.$fileSystem.write(file, response)
        .then((message) => {
          // Unzip zip files
          // console.timeEnd('fetchFile' + file);
          if (/\.zip$/i.test(file)) {
            return this.$fileSystem.unzip(message.file).then((result) => {
              this.$store.dispatch(STOP_DIMMER, {});
            }, (error) => {
              console.error(error);
              this.$store.dispatch(STOP_DIMMER, {});
            });
          } else {
            this.$store.dispatch(STOP_DIMMER, {});
            return message;
          }
        });
    })
    .catch(error => {
      console.error(error);
      this.$store.dispatch(STOP_DIMMER, {});
    });
}

The function is called the same way - here for the thumbnails:

function saveThumbnails(documents) {
   let promises = documents.map((imagePath) => {
    if (imagePath) {
      downloadAndWrite.call(this, imagePath)
    }
  });

  return Promise.all(promises);
}

for the files: (sometimes a download will contain more than 1 file)

let promises = resources.map((item) => {
  if (item && item.url) {
    downloadAndWrite.call(this, item.url);
  } else {
    console.error('missing url', item);
  }
});
return Promise.all(promises);

Does anybody know why my app at the file download freezes? FYI: After the freeze ends, the download will be started and everything works.


Solution

  • So guys i solved it! It was the axios repo and the promises while sending requests. Ive tested with superagent and http. They were faster but not fast enough. This is my solution:

    let responseType = 'arraybuffer';
    if (this.$q.platform.is.cordova) {
      responseType = 'blob';
    }
    return new Promise((resolve, reject) => {
    let length = files.length;
    let count = 0;
    files.map((imagePath) => {
      if (imagePath) {
        let request = new XMLHttpRequest();
        request.open('GET', imagePath);
        request.responseType = responseType;
        request.timeout = 1800000;
    
        request.addEventListener('load', (event) => {
          if (request.status >= 200 && request.status < 300) {
            this.$fileSystem.write(imagePath, request.response)
              .then((message) => {
                // Unzip zip files
                if (/\.zip$/i.test(message.file)) {
                  this.$fileSystem.unzip(message.file).then((result) => {
                    this.$emit('download-finished', message);
                  }, (error) => {
                    console.error(error);
                    this.$emit('download-finished', message);
                  });
                } else {
                  this.$emit('download-finished', message);
                  // return message;
                }
              });
          } else {
            console.warn(request.statusText, request.response);
            this.$emit('download-finished', request.response);
          }
        });
        request.send();
      }
    });
    this.$on('download-finished', (response) => {
      count++;
      console.log('download-finished ' + count);
      if (count === length) {
        resolve();
      }
    })
    });
    

    Hope this helps someone