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 -&g…


This content originally appeared on DEV Community and was authored by NordicBeaver

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 ;).


This content originally appeared on DEV Community and was authored by NordicBeaver


Print Share Comment Cite Upload Translate Updates
APA

NordicBeaver | Sciencx (2021-09-27T20:08:15+00:00) A real-life example of making a custom Promise in JavaScript/TypeSctipt. Retrieved from https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/

MLA
" » A real-life example of making a custom Promise in JavaScript/TypeSctipt." NordicBeaver | Sciencx - Monday September 27, 2021, https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/
HARVARD
NordicBeaver | Sciencx Monday September 27, 2021 » A real-life example of making a custom Promise in JavaScript/TypeSctipt., viewed ,<https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/>
VANCOUVER
NordicBeaver | Sciencx - » A real-life example of making a custom Promise in JavaScript/TypeSctipt. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/
CHICAGO
" » A real-life example of making a custom Promise in JavaScript/TypeSctipt." NordicBeaver | Sciencx - Accessed . https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/
IEEE
" » A real-life example of making a custom Promise in JavaScript/TypeSctipt." NordicBeaver | Sciencx [Online]. Available: https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/. [Accessed: ]
rf:citation
» A real-life example of making a custom Promise in JavaScript/TypeSctipt | NordicBeaver | Sciencx | https://www.scien.cx/2021/09/27/a-real-life-example-of-making-a-custom-promise-in-javascript-typesctipt/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.