It’s the start of a new year, and while lots of folks are promising to be more active, I’m going to show you how to make s to be more lazy… s, that is. Promise JavaScript Promise It’ll make more sense in a moment. https://www.youtube.com/watch?v=qj7diPVWTqY?embedable=true First, let’s look at a basic example. Here, I have a function called sleep that takes a time in milliseconds and a value. It returns a promise that will execute a for the number of milliseconds that we should wait; then the Promise resolves with the value. Promise setTimeout /** * @template ValueType * @param {number} ms * @param {ValueType} value * @returns {Promise<ValueType>} */ function sleep(ms, value) { return new Promise((resolve) => { setTimeout(() => resolve(value), ms); }); } It works like this: We can await the function with the arguments and , and after one second, the will log the string, ‘Yawn & stretch’. sleep 1000 'Yawn & stretch' console There’s nothing too special about that. It probably behaves as you would expect, but it gets a little weird if we store it as a variable to later on, rather than ing the returned right away. await await Promise const nap = sleep(1000, 'Yawn & stretch') Now, let’s say we do some other work that takes time (like typing out the next example), and then the variable. await nap You might expect a one-second delay before resolving, but in fact, it resolves immediately. Anytime you create a , you instantiate whatever asynchronous functionality it’s responsible for. Promise In our example, the moment we define the variable, the gets created which executes the . Because I’m a slow typer, the will be resolved by the time we it. nap Promise setTimeout Promise await In other words, s are eager. They do not wait for you to them. Promise await In some cases, this is a good thing. In other cases, it could lead to unnecessary resource use. For those scenarios, you may want something that looks like a , but uses to only instantiate when you need it. Promise lazy evaluation Before we continue, I want to show you something interesting. s are not the only things that can be ed in JavaScript. If we create a plain with a method, we can actually that object just like any . Promise await Object .then() await Promise This is kind of weird, but it also allows us to create different objects that like s, but aren’t. These objects are sometimes called “ “. look Promise Thenables With that in mind, let’s create a new called that extends the built-in constructor. Extending Promise isn’t strictly necessary, but it makes it appear more similar to a using things like . class LazyPromise Promise Promise instanceof class LazyPromise extends Promise { /** @param {ConstructorParameters<PromiseConstructor>[0]} executor */ constructor(executor) { super(executor); if (typeof executor !== 'function') { throw new TypeError(`LazyPromise executor is not a function`); } this._executor = executor; } then() { this.promise = this.promise || new Promise(this._executor); return this.promise.then.apply(this.promise, arguments); } } The part to focus on is the method. It hijacks the default behavior of a standard to wait until the method is executed before creating a real . then() Promise .then() Promise This avoids instantiating the asynchronous functionality until you actually call for it. And It works whether you explicitly call or use . .then() await Now, let’s see what happens if we replace the in the original function with a . Once again, we’ll assign the result to a variable. Promise sleep LazyPromise nap function sleep(ms, value) { return new LazyPromise((resolve) => { setTimeout(() => resolve(value), ms); }); } const nap = sleep(1000, 'Yawn & stretch') Then we take our time to type out the line and execute it. await nap This time, we see a one-second delay before the resolves regardless of how much time passed since the variable was created. Promise (Note that this implementation only creates the new once and references it in subsequent calls. So if we were to it again, it would resolve immediately like any normal ) Promise await Promise Of course, this is a trivial example that you probably won’t find in production code, but there are many projects that use lazy-evaluated -like objects. Probably the most common example is with database s and query builders like or . Promise ORM Knex.js Prisma Consider the pseudo-code below. It’s inspired by some of these query builders: const query = db('user') .select('name') .limit(10) const users = await query We create a database query that goes to the table and selects the first ten entries and returns their names. In theory, this would work fine with a regular . "user" Promise But what if we wanted to modify the query based on certain conditions like query string parameters? It would be nice to be able to continue modifying the query before ultimately awaiting the . Promise const query = db('user') .select('name') .limit(10) if (orderBy) { query.orderBy(orderBy) } if (limit) { query.limit(limit) } if (id) { query.where({ id: id }) } const users = await query If the original database query was a standard , it would eagerly instantiate the query as soon as we assigned the variable, and we wouldn’t be able to modify it later on. Promise With lazy evaluation, we can write code like this that’s easier to follow, improves the developer experience, and only executes the query once when we need it. That’s one example where lazy evaluation is great. It might also be useful for things like building, modifying, and orchestrating HTTP requests. Lazy s are very cool for the right use cases, but that’s not to say that they should replace every . In some cases, it’s beneficial to instantiate eagerly and have the response ready as soon as possible. Promise Promise This is another one of those “it depends” scenarios. But the next time someone asks you to make a , consider being lazy about it ( ͡° ͜ʖ ͡°). Promise Thank you so much for reading. If you liked this article, please . It's one of the best ways to support me. You can also or if you want to know when new articles are published. share it sign up for my newsletter follow me on Twitter Also published . here