angular - Vent på, at en asynkron funktion returnerer en værdi i Typescript


Jeg har en funktion (Function1), der kalder en anden funktion (Function2), som returnerer en streng.

Jeg vil have, at Function1 kalder Function2, men venter og får returværdien fra Function2. Hvordan gør man det? Her er min kode (som ikke fungerer som forventet):

Her er min Funktion1:

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

Her er min Funktion2:

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";
    });      
}

Svar #1

Hvis du bruger Promise.race som det andet svar foreslår, vil du ikke rydde op i event-handleren for den knap, der ikke blev trykket på. Du vil kun rydde op i handleren for den knap, der blev trykket på. Hvis det var mig, ville jeg blot kombinere event-handlerne for at sikre, at alt bliver ryddet op, når en hvilken som helst knap trykkes:

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

Og det kunne skaleres til et vilkårligt antal knapper:

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

Svar #2

Ændre

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

});

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

Til

return Promise.race([
    doneButtonPromise.then(() => {
        console.log("DONE BUTTON PRESSED!");
        return "Confirm";
    }),
    cancelButtonPromise.then(() => {
        console.log("CANCEL BUTTON PRESSED!");
        return "Cancel";
    })
]);

Relaterede artikler