Transmit the canvas image and anticipate the AJAX POST response

I need to send canvas content to my API endpoint using ajax and wait for the response before moving on to the next function. Here is my current sending function:

function sendPicture(){
  var video = document.getElementById('video');
  var canvas = document.getElementById('canvas');

  var context = canvas.getContext('2d');
  if (width && height) {
    canvas.width = width;
    canvas.height = height;
    context.drawImage(video, 0, 0, width, height);

    var fd = new FormData();
    fd.append('video', null);

    var reso;
    canvas.toBlob(function(blob){
        fd.set('video', blob);
    }, 'image/jpeg');

    reso = $.ajax({
      url: "/img",
      type : "POST",
      processData: false,
      contentType: false,
      data : fd,
      dataType: "text",
    });

    return reso;
  }
}

The ajax statement works within the toBlob callback, but I lose access to the main scope. I'd like to find a way to block the ajax promise outside of the callback. Perhaps extracting the blob argument from the callback scope or ensuring that fd.set('video', blob) sets the formData object outside where it was initially created would help.

Any suggestions on how to convert the canvas to a blob without using the callback method? Or any ideas on how to fill the formData in the outer scope?

Answer №1

There is a method to obtain the width and height, though it may be confusing at first glance. The key is to create a function outside of the callback and then invoke it within the callback. This allows you to access the data from both inside and outside of the callback.

function sendPicture(){
     var video = document.getElementById('video');
     var canvas = document.getElementById('canvas');

     var context = canvas.getContext('2d');
     if (width && height) {
       canvas.width = width;
       canvas.height = height;
       context.drawImage(video, 0, 0, width, height);
     }

     var fd = new FormData();
     fd.append('video', null);

     var setBlobOutside = function(blob){
       fd.set('video', blob);
     }
     
     var reso;
     canvas.toBlob(function(blob){
         setBlobOutside(blob);
     }, 'image/jpeg');

     reso = $.ajax({
       url: "/img",
       type: "POST",
       processData: false,
       contentType: false,
       data: fd,
       dataType: "text",
     });

     return reso;
}

Your var fd = new FormData(); is empty because it is not receiving any data or having anything appended to it. You can rectify this by using fd.append('key1', 'value1'); or new FormData([data]);

Below is an example demonstrating how to asynchronously send form data with a file:

<form id="formElem">
  <input type="text" name="firstName" value="John">
  Picture: <input type="file" name="picture" accept="image/*">
  <input type="submit">
</form>

<script>
  formElem.onsubmit = async (e) => {
    e.preventDefault();

    let response = await fetch('/article/formdata/post/user-avatar', {
      method: 'POST',
      body: new FormData(formElem)
    });

    let result = await response.json();

    alert(result.message);
  };
</script>

Answer №2

After finding inspiration in a discussion on how to access blob value outside of the canvas.ToBlob() async function, I opted to utilize a promise constructor for my project. Here is the code snippet showcasing the solution:

function uploadImage(width, height){
  var video = document.getElementById('video');
  var canvas = document.getElementById('canvas');

  var context = canvas.getContext('2d');
  canvas.width = width;
  canvas.height = height;
  context.drawImage(video, 0, 0, width, height);

  return new Promise(function(resolve, reject) {
    canvas.toBlob(function(blob) {
      var formData = new FormData();
      formData.set('image', blob);

      $.ajax({
        url: "/img/upload",
        type : "POST",
        processData: false,
        contentType: false,
        data : formData,
        dataType: "text",
      })
      .done(function(response) {
        resolve(response)
      })
      .fail(function(error) {
        console.log(error);
      });
    })
  })
}

This function can be called within an HTML script like so:

  <script>
    $(function() {
      var captureButton = document.getElementById("captureBtn");
      captureButton.addEventListener('click', function(event){
        var imageUploadPromise = uploadImage(300, 200);

        imageUploadPromise
        .then(function(response){
          console.log(response);
          displayUploadedPhoto();
        });
        event.preventDefault();
      }, false);
    })()
  </script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to obtain HTML code within a contentEditable DIV?

When working in a contentEditable-DIV, my goal is to extract the HTML code from the starting position (0) to the end position where the user has clicked. <div id="MyEditableId" contentEditable="true"> 1. Some text 123. <span style="background-c ...

Is it mandatory to employ the spread operator in the process of updating an object while using the useState hook?

Recently delving into hooks, I stumbled upon an insightful passage in the official documentation regarding Using Multiple State Variables: It is noteworthy that updating a state variable in hooks replaces it entirely, as opposed to merging it like in th ...

Issue with Rails - AJAX window.location redirect not functioning

When using AJAX in my Rails application, I encountered an issue where the redirect after a successful request was not working. The input is passed to the controller as stringified JSON through AJAX. Here is the code snippet: $.ajax({ url: "report/subm ...

When refreshed using AJAX, all dataTable pages merge into a single unified page

I followed the instructions on this page: How to update an HTML table content without refreshing the page? After implementing it, I encountered an issue where the Client-Side dataTable gets destroyed upon refreshing. When I say destroyed, all the data ...

Providing structured Express app to deliver HTML and JavaScript content

Currently, I am working with Express and facing a seemingly simple challenge. Here is the structure of my directories: |-config |---config.js |---routes.js |-server.js |-scripts |---controllers |------controllers.js |---directive ...

Encountered a problem while parsing an XML file using JavaScript from an external server

Currently, I am developing an iPhone application in HTML that needs to pull content from an XML file stored on a remote server and display it in a list. I have successfully accomplished this task when the XML file is hosted on the same server using the fo ...

Change the x and y positions of several div elements as the mouse moves in JavaScript

I am aiming to create a webpage where multiple divs with text and other content move along the x and y axes of the mouse. The desired effect is similar to parallax scrolling, but I have found that existing parallax plugins are image-based and do not work w ...

The image upload failed: the server could not locate the requested URL

I am completely new to working with Flask, and I'm currently in the process of creating a basic image uploading application. After comparing my code with various tutorials on how to build similar apps, it seems like everything is in place. However, w ...

Can TypeScript be used to dynamically render elements with props?

After extensive research on SO and the wider web, I'm struggling to find a solution. I have devised two components, Link and Button. In short, these act as wrappers for <a> and <button> elements with additional features like chevrons on t ...

I am frustrated because the csvtojson converter keeps replacing my file name with "undefined."

Despite running the csvtojson module on node.js successfully without any additional code, I encounter an issue when attempting to include it within a function. The result returns as undefined, even though the file path remains intact. Check out the JavaSc ...

Syntax error: Your code encountered an unexpected closing curly brace

Here is the code snippet I am working with: <?php session_start();?> <!DOCTYPE html> <html> <head> <title>Narcis Bet</title> <meta charset="utf-8"> <link rel="stylesheet" href="css/style.css" type="text/css"&g ...

Instructions on incorporating a new variable into the ajax script using the post method

I am facing an issue with sending a value from my PHP script using a variable named $topid. The goal is to pass this id to the getData.php script, so I attempted the following approach: $(document).ready(function(){ // Load more data $('.loa ...

AngularJS nested menu functionality not functioning properly

I am currently working on a nested menu item feature in AngularJS. I have a specific menu structure that I want to achieve: menu 1 -submenu1 -submenu2 menu 2 -submenu1 -submenu2 angular.module('myapp', ['ui.bootstrap']) .cont ...

Using private members to create getter and setter in TypeScript

Recently, I developed a unique auto getter and setter in JavaScript which you can view here. However, I am currently unsure of how to implement this functionality in TypeScript. I am interested in creating an Object Oriented version of this feature if it ...

What is the @page rule in Material-UI?

Trying to incorporate Material-UI styles with react-to-print to print components can be tricky, especially when dealing with a specific component that requires a particular page size. Here's an attempt at achieving this: const styles = (theme: Theme) ...

extracting and interpreting JSON information from a socket using Node.js

Looking for a solution to buffer JSON data received from client(s) on my node.js net tcp server until the entire block arrives. I'm considering either parsing it or forwarding it elsewhere. Are there any modules out there that are compatible with the ...

The $route.reload() function seems to be ineffective in Internet Explorer

I'm currently using AngularJs to develop an application. The issue I am encountering is related to data not being refreshed in IE, even after executing the $route.reload() function. Strangely enough, this problem only occurs in Internet Explorer and w ...

Ways to disseminate arguments when dealing with an array of arrays in JavaScript

Struggling to pass an array as arguments into the join method on path in node, but hitting a roadblock: var path = require("path"); var paths = [__dirname]; var userInput = ["app", "js"]; paths.push(userInput); var target = path.join.apply(null, paths); ...

Transfer data from a Django template populated with items from a forloop using Ajax to a Django view

Struggling to implement a click and populate div with ajax in my django e-commerce app. The function involves clicking on a category in the men's page which then populates another div. gender.html {%for cate in cat%} <a href="javascript:getcat()" ...

Retrieving JSON information stored in a JavaScript variable

I'm feeling a bit embarrassed to admit it, but I am still learning the ropes when it comes to Javascript development. I've hit a roadblock and could really use some help from the experts here. Thank you in advance for all the assistance this comm ...