30

I'm working with HTMLCanvas element that return the blob object outside of the async toBlob() function. This function doesn't return an output value, so I'm trying to declare a variable outside and access it through the command.

How I can use JS Promise for this scenario?

var myblob;
            canvas.toBlob(function(blob) {                         
                              myblob = blob;
                              console.log("inside " + myblob); // getting value after the console outside
                           })
 console.log( "outside " + myblob); // getting undefined   

2

4 Answers 4

87
const blob = await new Promise(resolve => canvasElem.toBlob(resolve));
Sign up to request clarification or add additional context in comments.

3 Comments

Bralliant indeed :)
Awesome! Could you, or anyone, explain it?
toBlob(resolve); // would be like toBlob(blob => resolve(blob));
28

You can use Promise constructor, pass Blob instance to resolve(), access Promise value at .then()

function getCanvasBlob(canvas) {
  return new Promise(function(resolve, reject) {
    canvas.toBlob(function(blob) {
      resolve(blob)
    })
  })
}

var canvasBlob = getCanvasBlob(canvas);

canvasBlob.then(function(blob) {
  // do stuff with blob
}, function(err) {
  console.log(err)
});

5 Comments

Thank you so much and apreciate your prompt response. My issue, is I have to set the value of blob in a global variable so that I can access it outside the this function. eg: inside the canvasBlob.then(function(blob)){ this.something = blob; }
You will not be able to access Blob until .toBlob() callback returns a value. Use first function passed to .then() to perform task with Blob from .toBlob() callback.
Thanks. In my scenario, I have a video element and canvas to capture a snapshot from the video and render it in an image control. Currently the code executes in the capturing mouse click event. Now, once I have the picture I have to let the user to click on a button send that picture to the server via ajax request. Currently toBlob() is executing in the capture event, i would like to see if there is way to get that blob stored so that i can access it in the button click event to submit it to the server. Any advise would be very helpful !
I think by calling the .toblob() second time in the button click returns the same image. Thank you !
Your initial attempt is close. When .toBlob() is called, assign myblob the value of Blob at .toBlob() callback. See also stackoverflow.com/questions/42234835/…
5

Typescript version:

function toBlob(canvas: HTMLCanvasElement): Promise<Blob> {
  return new Promise((resolve) => {
    canvas.toBlob(blob => {
      if (blob) resolve(blob);
    });
  });
}

Comments

4

I HAVE ANOTHER IDEA... similar to the one marked as best idea... the problem with then is that you have to be inside the block in order to pick up the result from the promise. Now Javascript supports await similar to c#, this is good because you can run the function and wait until is resolved, then you get the result to a variable not attached to any function, example:

/* basically we create a function that receives a canvas called mycanvas, then we tell the function to return a new Promise, this promise is "resolved" inside the .toBlob method which by default provides a Blob parameter. */

function getCanvasBlob(mycanvas) {
  return new Promise(function(resolve, reject) {
    mycanvas.toBlob((blob) => {
      resolve(blob)
    })
  })
}

var myblob;

try{
  myblob = await getCanvasBlob(CANVAS_FROM_SOMEWHERE);
}
catch (error){
  console.log(error);
}

/* There's no need to use try/catch, you could use it just like this */

var myblob = await getCanvasBlob(CANVAS_FROM_SOMEWHERE);

As the method is async, then() is not executed or called until the promise is resolved, anything outside this method will not be notified of changes until is too late... The advantage here is that our javascript will not continue until the promise has been fully resolved.

ADDITIONAL INFO: If you call await, the method from where you are calling this function must be marked as async, otherwise you will see an error... lets say for example this is called inside a click of a button:

/* OBVIOUSLY this will throw an error because I don't have a real canvas...*/

$( document ).ready(function() {
    
    $('#mybutton').bind('click', async function(){
    
      //...more code...
      //...more code... until...
      
      var CANVAS_FROM_SOMEWHERE;
      
      var myblob = await getCanvasBlob(CANVAS_FROM_SOMEWHERE);
    
    });
    
});

function getCanvasBlob(mycanvas) {
  return new Promise(function(resolve, reject) {
    mycanvas.toBlob((blob) => {
      resolve(blob)
    })
  })
}

   

    
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="mybutton">process my canvas!</button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.