Search code examples
angulartypescriptfunctionsynchronoussequential

How to implement synchronous functions in typescript (Angular)


I have a function that I want to run sequentially/synchronously, but my function is running asynchronously. I don't know how to make this synchronous. Here is the structure of the function.

let paymentStatus: boolean = false;
console.log('action 1');

if (paymentDetails != null) {
    console.log('action 2');

    var x = (window as any).getpaidSetup({
        callback: async (response) => {
            console.log('action 3');

            if (response != null) {
                console.log('action 4');
                paymentStatus = true;

            } else {
                console.log('still action 4');
            }
            console.log('action 5');
        }
    });

    console.log('action 6');
    return paymentStatus;
}

I want to perform "action 1, action 2, action 3, action 4, action 5 and action 6" before returning "paymentStatus", but the system is performing thus: "action 1, action 2, action 6, return operation, action 3, action 4, action 5". I've tried to use async and await, but to no avail.


Solution

  • You could use async await, but you first have to wrap your asynchronous part into a promise. That would look something like this:

    async function executeSequentially(paymentDetails) {
        let paymentStatus: boolean = false;
        console.log('action 1');
    
        if(paymentDetails != null) {        
            console.log('action 2');
    
            // Wrap the part that is asynchronous and await the promise
            await new Promise(resolve => {
                (window as any).getpaidSetup({           
                    callback: response => {  
                        console.log('action 3');
                        
                        if (response != null){   
                            console.log('action 4');
                            paymentStatus = true;
    
                        }else { 
                            console.log('still action 4');
                        }
                        console.log('action 5');
                        resolve(); // resolve the Promise when async execution finished
                    }
                });
            });
        }
    
        console.log('action 6');
    
        return paymentStatus;
    }
    

    And with a little bit of code cleanup, it could look something like this:

    // extract promisification into its own function (no need for async, you return a promise anyway)
    function promisifiedGetPaidSetup():Promise<boolean> {
        return new Promise(resolve =>
            (window as any).getpaidSetup({           
                // resolve with a boolean value, cleaner design since you don't set a variable outside
                callback: response => resolve(response != null) 
            })
        );
    }
    
    async function executeSequentially(paymentDetails):Promise<boolean> {
        // Either return the result from the promise, or false if payment details are not present
        return paymentDetails ? await promisifiedGetPaidSetup() : false;
    }
    

    Here a link to the Playground with the second example "in action". It is important to note that your code will still be asynchronous (that's why it returns a promise now, which are asynchronous by nature). But the statements inside will be executed in order. So wherever you use the executeSequentially function, you will have to await it if you want to run it pseudo-synchronously.