Search code examples
javascriptajaxasynchronousjszip

Return true/false from asynchronous function to use in synchronous if()


I'm creating simple upload form (for .zip files) and I want to validate if zip contains all files which will be necessary later.

so I have a function isZipCorrect():

isZipCorrect  = function() {
  'use strict';
  if (this.name.slice(-3) === 'zip') {
    var fileReader = new FileReader();
    var zip = new JSZip();
    var shpCorrect = false;
    fileReader.onload = function() {
      var zip = new JSZip(this.result);
      shpCorrect = zip.file(/.*?/).every(function(file) {
          return (file.name.slice(-3) === 'shp' ||
          file.name.slice(-3) === 'dbf' ||
          file.name.slice(-3) === 'shx');
    });
    console.log(shpCorrect);
    };
    fileReader.readAsArrayBuffer(this.file);
    return shpCorrect;
  } else {
    return true;
  }

and I use it in if(isZipCorrect()) before XMLHttpRequest.

I assume that the problem is asynchronous function (fileReader.onload) which end operation when whole code is already ended. But I don't want to call send function from fileReader.onload because for me checking is Zip correct must be optional (you should be able to upload other files which will go through without 'parsing')


Solution

  • You could use jQuery.Deferred() to do something like this:

    validateZipFile = function(file) {
      var 
        deferred = $.Deferred(),
        fileReader = new FileReader();
    
      fileReader.onload = function() {
        var zip = new JSZip(this.result);
        var isCorrect = zip.file(/.*?/).every(function(file) {
          return /\.(shp|dbf|shx)$/i.test(file.name)
        });
    
        isCorrect ? deferred.resolve() : deferred.reject();
      };
    
      if( !/\.(zip)$/i.test(file.name) ) {
        deferred.reject()
      } else {
        fileReader.readAsArrayBuffer(file)
      }
    
      return deferred.promise()
    };
    

    and call it like so:

    validateZipFile(file).done(submitForm).fail(handleBadZip);
    

    where 'submitForm' and 'handleBadZip' are functions you've previously defined