Home » Jquery » javascript – How to pass asynchronous function result into ajax function as parameter in js/jquery?-Exceptionshub

javascript – How to pass asynchronous function result into ajax function as parameter in js/jquery?-Exceptionshub

Posted by: admin February 24, 2020 Leave a comment

Questions:

I’m trying to save the base64 image code of a video snapshot…

To do that, I have a first function I found which builds the snapshot I want, this function, videoSnap, is asynchronous, and I’d like to send it through an ajax function for further actions.

Problem is that the result of my videoSnap is completed way after the ajax call, thus, anytime I’m trying to send the result as a parameter of the ajax function, the result stay undefined…

How can I do this to work? I thought about promise function with then() but still the same result… I keep getting the base64 code after the ajax call making it uneffective…

I’m starting to be short of solution and idea… ^^’

Thanks much in advance for your great help! 🙂

    getTime = function (){
        var t = new Date();
        return t.getTime();
    }

    dump = function (r) {
        var pre = document.createElement('pre');
        pre.innerHTML = r;
        document.body.appendChild(pre)
    }

    videoSnap = function (file){
        var reader = new FileReader();
        if (file.type.match('video')) {
            reader.onload = function() {
              var blob = new Blob([reader.result], {type: file.type});
              var url = URL.createObjectURL(blob);
              var video = document.createElement('video');
              var timeupdate = function() {
                var snap = snapImage();
                if (snap.success) {
                  video.removeEventListener('timeupdate', timeupdate);
                  video.pause();
                  dump(getTime()+' : '+snap.image);
                  return snap.image;
                }else{
                  return false;
                }
              };
              video.addEventListener('loadeddata', function() {
                var snap = snapImage();
                if (snap.success) {
                  video.removeEventListener('timeupdate', timeupdate);
                  dump(getTime()+' : '+snap.image);
                  return snap.image;
                }else{
                  return false;
                }
              });
              var snapImage = function() {
                var canvas = document.createElement('canvas');
                canvas.width = video.videoWidth;
                canvas.height = video.videoHeight;
                canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
                var image = canvas.toDataURL();
                var success = image.length > 100000;
                var result = { success: success, image: image };
                return result;
              };
              video.addEventListener('timeupdate', timeupdate);
              video.preload = 'metadata';
              video.src = url;
              // Load video in Safari / IE11
              video.muted = true;
              video.playsInline = true;
              video.play();
            };
            reader.readAsArrayBuffer(file);
        }else{
            return false;
        }
    }

    dump(getTime());

    var base64Img = videoSnap(videoFile);

    formData.append("videoSnap",base64Img);

    /*
    function videoSnapPromise(vid) {
        return new Promise((resolve) => {
        resolve(videoSnap(vid));
      })
    }   
    function appendResolve(resolve) {
        formData.append("videoSnap",resolve);
    }

    const promise = videoSnap(videoFile);
    promise.then(appendResolve);
    */

    dump(getTime());

    $.ajax({
        type: 'POST',
        url: 'uploadBase64Img.php',
        timeout: 10000,
        data: formData,
        processData: false, 
        contentType: false, 
        dataType: "json",
        complete: function() {
            // complete function
        }
    });

    dump(getTime());
How to&Answer:

One way to do this would be to create a callback function and send it to the first function as a parameter, then refactor your first function to call that callback and pass it the result of the operation instead of returning it.

something like this should work:

getTime = function() {
  var t = new Date();
  return t.getTime();
}

dump = function(r) {
  var pre = document.createElement('pre');
  pre.innerHTML = r;
  document.body.appendChild(pre)
}


var videoSnap = function(file, callback) {
  var reader = new FileReader();
  if (file.type.match('video')) {
    reader.onload = function() {
      var blob = new Blob([reader.result], {
        type: file.type
      });
      var url = URL.createObjectURL(blob);
      var video = document.createElement('video');
      var timeupdate = function() {
        var snap = snapImage();
        if (snap.success) {
          video.removeEventListener('timeupdate', timeupdate);
          video.pause();
          dump(getTime() + ' : ' + snap.image);
          callback(snap.image);
        } else {
          callback(false);
        }
      };
      video.addEventListener('loadeddata', function() {
        var snap = snapImage();
        if (snap.success) {
          video.removeEventListener('timeupdate', timeupdate);
          dump(getTime() + ' : ' + snap.image);
          callback(snap.image);
        } else {
          callback(false);
        }
      });
      var snapImage = function() {
        var canvas = document.createElement('canvas');
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
        var image = canvas.toDataURL();
        var success = image.length > 100000;
        var result = {
          success: success,
          image: image
        };
        callback(result);
      };
      video.addEventListener('timeupdate', timeupdate);
      video.preload = 'metadata';
      video.src = url;
      // Load video in Safari / IE11
      video.muted = true;
      video.playsInline = true;
      video.play();
    };
    reader.readAsArrayBuffer(file);
  } else {
    callback(false);
  }
}



var doAjax = function(base64Img) {
  var formData = FormData();
  formData.append("videoSnap", base64Img);
  $.ajax({
    type: 'POST',
    url: 'uploadBase64Img.php',
    timeout: 10000,
    data: formData,
    processData: false,
    contentType: false,
    dataType: "json",
    complete: function() {
      // complete function
    }
  });

}


videoSnap(videoFile, doAjax);