0

I am trying to convert an img URL to a var that I can use elsewhere in my code.

So far, I have the following approach:

function toDataUrl(src) { // Create an Image object var img = new Image(); // Add CORS approval to prevent a tainted canvas img.crossOrigin = 'Anonymous'; // Load the image img.src = src; // make sure the load event fires for cached images too if (img.complete || img.complete === undefined) { // Flush cache img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; // Try again img.src = src; } img.onload = function() { // Create an html canvas element var canvas = document.createElement('CANVAS'); // Create a 2d context var ctx = canvas.getContext('2d'); var dataURL; // Resize the canavas to the original image dimensions canvas.height = this.naturalHeight; canvas.width = this.naturalWidth; // Draw the image to a canvas ctx.drawImage(this, 0, 0); // Convert the canvas to a data url dataURL = canvas.toDataURL(outputFormat); // Mark the canvas to be ready for garbage // collection canvas = null; // Return the data url via callback // callback(dataURL); return dataURL; }; } var myimg = toDataUrl('/media/signatures/signature.8.png'); 

However, myimg returns undefined. I think this is because it might be loading asynchronously. I have refered to this answer however it does not explain how to set the callback as a global variable.

How can I set myimg = dataURL? Is there a way to do this without a callback?

4
  • 1
    There's FileReader object doing that for you. Commented Apr 28, 2020 at 0:32
  • 1
    The thing is, you can't return anything from within that load Event. Why not pass a function as an argument that you pass dataURL into? function toDataURL(src, func){ /* code, code, code */ img.onload = function(){ /* code, code, code */ func(dataURL); }/*blah, blah */ Commented Apr 28, 2020 at 0:33
  • 1
    You can't break the laws of JavaScript physics and have an asynchronously derived result return immediately from a function call. You'll have to go the Promise or basic callback route to get what you need. There's no way around it. Commented Apr 28, 2020 at 0:36
  • @RoboRobok per stackoverflow.com/a/20285053/2429989 doesn't FileReader also require a callback? Commented Apr 28, 2020 at 1:46

1 Answer 1

1

There's no way to break the entire execution model of JavaScript in order to get your asynchronously-populated variable returned from your function call.

Although this uses callbacks behind the scenes, you may find using an async function pattern to relieve the burden of needing to use callbacks.

function toDataUrl(src) { // Create an Image object var img = new Image(); // Add CORS approval to prevent a tainted canvas img.crossOrigin = 'Anonymous'; // Load the image img.src = src; // make sure the load event fires for cached images too if (img.complete || img.complete === undefined) { // Flush cache img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; // Try again img.src = src; } return new Promise((resolve, reject) => { img.addEventListener('load', () => { // Create an html canvas element var canvas = document.createElement('CANVAS'); // Create a 2d context var ctx = canvas.getContext('2d'); var dataURL; // Resize the canavas to the original image dimensions canvas.height = this.naturalHeight; canvas.width = this.naturalWidth; // Draw the image to a canvas ctx.drawImage(this, 0, 0); // Convert the canvas to a data url dataURL = canvas.toDataURL(outputFormat); // Mark the canvas to be ready for garbage // collection canvas = null; resolve(dataURL); }); img.addEventListener('error', reject); }); } 

This now can be consumed within an async function thusly:

async function doSomething() { const myimg = await toDataUrl('/media/signatures/signature.8.png'); } 

Keep in mind that doSomething is now also asynchronous, so anything calling it now has to await as well (or use Promise callbacks).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.