Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 27, 2021 08:08 pm GMT

A real-life example of making a custom Promise in JavaScript/TypeSctipt

It feels like we've completely moved from callbacks to Promises and async/await in the JavaScript world. So much, that almost every library and framework provides async versions of their functions. And the logic usually goes like this: 'I see async -> I type await and mark my function async as well -> done!'. I got so used to it, so I started to forget how to create and use my own Promises.

But life always finds a way to remind you that old habits die hard, especially if you're talking about browsers APIs.

So, if you're like me and need a little reminder on how to make custom Promises, I hope you'll find this post helpful.

Creating html images.

So here is the problem. We need to create an Image element using a browser's API and set its source to a dataUrl of some picture. At first, I wrote something like this.

function drawImage(dataUrl: string) {  const image = new Image();  image.src = dataUrl;  return image;};

Looks great, but there is a problem here. When we set image.src it's not instantly loaded. Even if a source is a data string, and not an URL to an external resource, it still takes time. So when an image is returned from the function, the is no guarantee that the data is already there.

Unfortunately, if you want to wait for the loading to be done, you can't do something like this.

function drawImage(dataUrl: string) {  const image = new Image();  await image.src = dataUrl; // STOP! THIS IS ILLEGAL!  return image;};

The only way is to set an event handler. But what do we put here?

function drawImage(dataUrl: string) {  const image = new Image();  image.addEventListener('load', () => {    // ???  });  image.src = dataUrl;  return image;};

If we were still in 2010, we would solve this by having another argument for a callback function.

function drawImage(dataUrl: string, onDone: () => void) {  const image = new Image();  image.addEventListener('load', () => {    onDone();  });  return image;};

But wait, it's 2021. Cool kids don't do that anymore. What we need, is to make our function return something awaitable. And there is nothing more awaitable than a Promise. Here is the Promise constructor

function Promise<T>(  executor: (    resolve: (value: T) => void,     reject: (reason?: any) => void  ) => void)

Looks a bit scary, but you just need to get to know it better. This is how you usually call it.

const promise = new Promise((resolve, reject) => {  // Lalala, do some work  // ....  if (we_are_good_and_got_the_result) {    resolve(result);  } else {    reject(error);  }})

So you pass a function in the constructor. A function that has 2 arguments, which are also functions. Call them resolve and reject. In that function we do some work. If everything went well, just call resolve with the result. Otherwise call reject with an error object.
The thing that you passed into the resolve is gonna be returned as a Promise result when it resolves.

Then you can use this new object.

promise.then((result) => {  // Use the result}).catch(error => {  // Oh no there was an error})

And, what's even better, you can also do this.

const result = await promise;

Let's apply what we learned to our problem.

function drawImage(dataUrl: string) {  const promise = new Promise<HTMLImageElement>((resolve, reject) => {    const image = new Image();    image.addEventListener('load', () => {      resolve(image);    });    image.src = dataUrl;  });  return promise;}

Then you can call your new function with await.

const image = await drawImage('data');

And that's it. We've done it!

Bonus example for those who can't wait.

The is one more example I want to show you. It's actually quite useful to be able to just wait for a set amount of time. Sadly, there is not wait() or sleep() function in JavaScript. But with our new powers we can make our one. Here is a quick one-liner for you guys to try and figure out as an exercise (I feel like a college teacher by saying this lol)

const wait = async (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

Show me more please Senpai.

This article is actually an extended version of an excerpt of my latest video. You're welcome to watch it if you want more ;).


Original Link: https://dev.to/nordicbeaver/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt-5d1n

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To