Search code examples
javascriptecmascript-6es6-promise

Javascript converting to blob undefined


I am having an undefined value when I tried to convert my canvas to a blob. I have this code below which works fine, but when I tried to move the console log below to the function then it gives me undefined.

Here is the working code:

    const handleSave = (params) => {
    
    let previewUrl;
    previewCanvasRef.current.toBlob(
      (blob) => {
        previewUrl = window.URL.createObjectURL(blob);
        console.log(previewUrl);                  
      },
      'image/png',
      1
    );
}

when I tried to make the console log below. then It gives me an undefiend value:

const handleSave = (params) => {
    
    let previewUrl;
    previewCanvasRef.current.toBlob(
      (blob) => {
        previewUrl = window.URL.createObjectURL(blob);
        
      },
      'image/png',
      1
    );

    console.log(previewUrl);
}

Here is what I've tried but error:

const handleSave = (params) => {
    
    let previewUrl;
    previewCanvasRef.current.toBlob(
      async (blob) => {
        previewUrl = window.URL.createObjectURL(blob);        
      },
      'image/png',
      1
    ).then((res) => console.log(res));  
}

Solution

  • This is the syntax you're looking for to turn this into an asynchronous function:

    const canvasToBlob = () => new Promise((resolve, reject) => {
      previewCanvasRef.current.toBlob(resolve, 'image/png', 1);
    });
    
    const handleSave = async () => {
      const blob = await canvasToBlob();
      const previewURL = URL.createObjectURL(blob);
    }
    

    Because async/await is just syntax sugar for wrapping Promises, if you want to create your own async function out of a traditional callback-style function, you would need to use Promises manually (since you can't return to exit the canvasToBlob function from within the callback of toBlob, as that would simply return the toBlob method).

    So, here, we simply tell toBlob to use resolve as its callback: a Promise's resolve(arg) is equivalent to an async function's return arg (and reject(err) is equivalent to throw err). In this case, the Blob being passed to the toBlob callback is arg. We can now use this function with async/await syntax sugar.

    Just keep in mind that, when you're using asynchronous functions, your entire chain needs to be in async mode: every function down the line that depends on this blob will need to be either wrapped with async/await syntax or .then'd—because a synchronous function cannot depend on an asynchronous value. In the real world, all that means is that you gotta remember to define your functions as async.

    This page from MDN will provide you with some more detailed readings on asynchronous functions in JS.