DEV Community

Viktor Shcheglov
Viktor Shcheglov

Posted on

Implementing a "Defer" Class in TypeScript

When working with asynchronous operations in JavaScript and TypeScript, Promises are the heart and soul of managing those operations. However, there are cases where the traditional promise patterns such as .then() and async/await might not give you the level of control you require. In such cases, having a Defer class can provide a more flexible way to handle promises.

In this article, we'll explore how to implement a Defer class in TypeScript, which allows for manually controlling the resolution and rejection of a promise.

What is a Defer?

In some programming contexts, a "defer" refers to a construct used to put off an operation until later. In the realm of promises, a Defer class can be used to create a promise whose resolution or rejection can be controlled externally, giving the programmer greater control over asynchronous flows.

Implementing Defer in TypeScript

Let's dive into how we can implement such a class in TypeScript:

class Defer<T> {
    promise: Promise<T>;
    resolve: (value: T | PromiseLike<T>) => void;
    reject: (reason?: any) => void;

    constructor() {
        this.promise = new Promise<T>((resolve, reject) => {
            this.resolve = resolve;
            this.reject = reject;
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

In this implementation, Defer<T> is a generic class where T represents the type of value the promise will resolve with. The constructor of this class creates a new promise, storing the resolve and reject functions as class properties. This allows you to invoke these functions outside the initial promise constructor context, thereby controlling the promise's outcome manually.

Usage

Here is how you could use the Defer class:

const myDefer = new Defer<number>();
myDefer.promise.then(value => console.log(`Resolved value: ${value}`));

// Somewhere else in the code
myDefer.resolve(42);  // Outputs: Resolved value: 42
Enter fullscreen mode Exit fullscreen mode

In this example, we create an instance of Defer<number>, meaning our promise will resolve with a number. We then add a .then() method to handle the resolution case. Since resolve and reject are controlled externally, we can call myDefer.resolve(42) anywhere in our code to resolve the promise.

Why Use a Defer?

While it's not common to need a Defer in everyday coding with promises, there are specific scenarios where it can be invaluable:

Complex asynchronous control flow: When dealing with multiple asynchronous sources that need to be synchronized in unconventional ways.
Testing and Mocking: **When testing, you might want to resolve or reject promises at specific times to simulate different scenarios.
**Advanced Resource Management:
In cases where resources need to be initialized asynchronously and controlled explicitly.

Conclusion

While the need for a Defer class is not everyday, its availability can simplify complex asynchronous handling scenarios, making code cleaner and more understandable. Remember, with great power comes great responsibility: use it wisely and sparingly.

I hope this guide helps you understand how and when to implement a Defer class in your TypeScript projects. Happy coding!

Discover Defer in Practice

Interested in seeing Defer in real-world scenarios?

Video Walkthrough: Dive into a live demonstration where I showcase the Defer class's applications. https://www.youtube.com/watch?v=Gco9RBubWU8

In-depth Article: Prefer reading? Explore a detailed guide that expands on Defer's usage and benefits. https://dev.to/shcheglov/make-dialog-component-like-a-hero-24e3

Enhance your async handling skills with these resources!

links: https://github.com/shogogg/ts-deferred

Top comments (0)