I'am trying to learn how to make SuperMario in JavaScript from here Can someone explain flow of the below function LoadImage ?
function loadImage(url) { return new Promise(resolve => { const image = new Image(); image.addEventListener('load', () => { resolve(image); }); image.src = url; }); } const canvas = document.getElementById('screen'); const context = canvas.getContext('2d'); context.fillRect(0,0,50,50); loadImage('/img/tiles.png') .then(image=>{ context.drawImage(image,0,0); // the function LoadImage returns a Promise with image object(which is a constant) // as parameter and if the promise is fulfilled then the image is drawn. / });
EDIT
I do understand how to use => operator. Which is used to make length of functions smaller.
image.addEventListener('load', () => { resolve(image);
the above line means that the promise is fulfilled when image is loaded. So does this mean that the following line is executed and then the event listener is waiting for the image to be downloaded in client browser ?
image.scr = url;
The flow of the below function is a little fuzzy to me
function loadImage(url) { return new Promise(resolve => { const image = new Image(); image.addEventListener('load', () => { resolve(image); }); image.src = url; });
EDIT 2:
Okay, this was a stupid post. And yup as the IMAGE from url is loaded in the image object then Event listener fires up the resolve().
A Promise is a JavaScript object that links producing code and consuming code.
As of ES6 (ES2015), promises are built into the Javascript specification and implementations to that spec.
The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value. To learn about the way promises work and how you can use them, we advise you to read Using promises first.
The code you are showing introduces an asynchronous primitive, Promise, which can be passed around and used to access a resource that hasn't been populated yet.
In this case, you want an Image
that is fully loaded and has image data that you can use. However, you can't access the image data until a network request finishes that would fetch the image data.
For example, this won't work:
const img = new Image(); img.src = "example.com/house.jpg"; ctx.drawImage(img, 0, 0); // img isn't done loading yet
Instead, we have to wait until the loading is done. There are a lot of ways to do that but the most common conventions are to use, callbacks, Promises, or async/await.
The method that you have shown combines callbacks and Promises (out of necessity).
Let's break down the code:
/** * Load an image from a given URL * @param {String} url The URL of the image resource * @returns {Promise<Image>} The loaded image */ function loadImage(url) { /* * We are going to return a Promise which, when we .then * will give us an Image that should be fully loaded */ return new Promise(resolve => { /* * Create the image that we are going to use to * to hold the resource */ const image = new Image(); /* * The Image API deals in even listeners and callbacks * we attach a listener for the "load" event which fires * when the Image has finished the network request and * populated the Image with data */ image.addEventListener('load', () => { /* * You have to manually tell the Promise that you are * done dealing with asynchronous stuff and you are ready * for it to give anything that attached a callback * through .then a realized value. We do that by calling * resolve and passing it the realized value */ resolve(image); }); /* * Setting the Image.src is what starts the networking process * to populate an image. After you set it, the browser fires * a request to get the resource. We attached a load listener * which will be called once the request finishes and we have * image data */ image.src = url; }); } /* * To use this we call the loadImage function and call .then * on the Promise that it returns, passing a function that we * want to receive the realized Image */ loadImage("example.com/house.jpg").then(houseImage => { ctx.drawImage(houseImage, 0, 0); });
In all honesty though, the loadImage
function could be a little bit more robust since it doesn't handle errors right now. Consider the following enhancement:
const loadImage = (url) => new Promise((resolve, reject) => { const img = new Image(); img.addEventListener('load', () => resolve(img)); img.addEventListener('error', (err) => reject(err)); img.src = url; }); loadImage("example.com/house.jpg") .then(img => console.log(`w: ${img.width} | h: ${img.height}`)) .catch(err => console.error(err));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With