Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for async function to return a value in Typescript.

I have a function (Function1) that calls another function (Function2) that returns a string.

I want Function1 to call Function2, but wait and get the return value of Function2. How do you go about doing that? Here's my code (which does not work as intended):

Here is my Function1:

async Function1() {
    const message = await this.dialogButtonPress();
    alert(message);
}

Here is my Function2:

async dialogButtonPress() : Promise<string> {
    const doneButtonPromise = new Promise((resolve) => {
        const doneButton = document.getElementById("done-button");
        const resolver = () => {
            resolve();
            doneButton.removeEventListener("click", resolver);
        }
        doneButton.addEventListener("click", resolver);
    });

    const cancelButtonPromise = new Promise((resolve) => {
        const cancelButton = document.getElementById("cancel-button");
        const resolver = () => {
            resolve();
            cancelButton.removeEventListener("click", resolver);
        }
        cancelButton.addEventListener("click", resolver);
    })

    doneButtonPromise.then(() => {
        console.log("DONE BUTTON PRESSED!");
        return "Confirm";

    });

    cancelButtonPromise.then(() => {
        console.log("CANCEL BUTTON PRESSED!");
        return "Cancel";
    });      
}
like image 851
Roka545 Avatar asked Jan 27 '26 04:01

Roka545


2 Answers

If you use Promise.race as the other answer suggests, you won't be cleaning up the event handler for the button that was not pressed. You'll be cleaning up only the handler for the button that was pressed. If it were me, I'd just combine the event handlers to ensure that everything is cleaned up when any button is pressed:

async dialogButtonPress(): Promise<string> {
    return new Promise<string>((resolve) => {
        const doneButton = document.getElementById("done-button")!;
        const cancelButton = document.getElementById("cancel-button")!;
        const resolver = (ev: Event) => {
            doneButton.removeEventListener("click", resolver);
            cancelButton.removeEventListener("click", resolver);
            // This is where we determine which button was clicked.
            resolve(ev.target === doneButton ? "Confirm" : "Cancel");
        }
        doneButton.addEventListener("click", resolver);
        cancelButton.addEventListener("click", resolver);
    });
}

And it could scale to any number of buttons:

async dialogButtonPress(): Promise<string> {
    return new Promise<string>((resolve) => {
        // You just need to expand this map in order to support additional buttons.
        const idToResponse: Record<string, string> = {
            "done-button": "Confirm",
            "cancel-button": "Cancel",
        };
        const buttons = Object.keys(idToResponse).map((id) => document.getElementById(id)!);
        const resolver = (ev: MouseEvent) => {
            for (const button of buttons) {
                button.removeEventListener("click", resolver);                    
            }
            // We index into idToResponse to convert the button's id to a specific response.
            resolve(idToResponse[(ev.target as Element).id]);
        }

        for (const button of buttons) {
            button.addEventListener("click", resolver);
        }
    });
}
like image 168
Louis Avatar answered Jan 29 '26 20:01

Louis


Change

doneButtonPromise.then(() => {
    console.log("DONE BUTTON PRESSED!");
    return "Confirm";

});

cancelButtonPromise.then(() => {
    console.log("CANCEL BUTTON PRESSED!");
    return "Cancel";
});

To

return Promise.race([
    doneButtonPromise.then(() => {
        console.log("DONE BUTTON PRESSED!");
        return "Confirm";
    }),
    cancelButtonPromise.then(() => {
        console.log("CANCEL BUTTON PRESSED!");
        return "Cancel";
    })
]);
like image 27
CRice Avatar answered Jan 29 '26 20:01

CRice



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!