Home > Software design >  Why does my function not wait for Promise to resolve?
Why does my function not wait for Promise to resolve?

Time:10-08

checkout.ts

renderButton(){
   renderShadowDomButton(); 
   let globalValue = getGlobalValue()
}

web_component_render.ts

let globalValue; 

async asyncFunction() {
   let booleanFromAsync = await someExternalAPICall(); 
   return booleanFromAsync; 
}

function renderShadowDOMButton() {
    asyncFunction.then((booleanFromAsync) => {
        globalValue = booleanFromAsync;
    })
}

export function getGlobalValue() {
    return globalValue;
}

I want to fetch the boolean after the async call is completed. My understanding was .then should ensure that the block of code in then will be executed after the promise resolved. However, while waiting for execution of the someExternalAPICall, it moves forward and gets the globalValue. The new global value is then updated after the async call completes. How can I ensure the code completes asyncFunction call and then gets the globalValue?

CodePudding user response:

Let's dissect and see what happens in your code here:

renderButton(){
   renderShadowDomButton(); 
   let globalValue = getGlobalValue()
}

renderShadowDomButton will call some random API in asyncFunction. While the API call is being made, JS then runs let globalValue = getGlobalValue(). At this point, the API call is not done yet. Hence, globalValue will be undefined.


If you want it to run one after the other, try the following:

web_component_render.ts

let globalValue; 

async asyncFunction() {
   return await someExternalAPICall(); 
}

async function renderShadowDOMButton() {
    globalValue = await asyncFunction();
}

export function getGlobalValue() {
    return globalValue;
}

checkout.ts

async renderButton(){
   await renderShadowDomButton(); 
   const globalValue = getGlobalValue()
}

However, I'll go one step further and help you refactor:

checkout.ts

async renderButton(){
   const globalValue = await getGlobalValue(); 
}

web_component_render.ts

export function getGlobalValue() {
    return await someExternalAPICall();
}

As much as possible, we do not want any global var even within the same file. Keep them scoped well. Also, take note of the asynchronous of JS.

CodePudding user response:

renderShadowDOMButton is an asynchronous function that means the code you put after it will continue executing without waiting for it to finish.

in order to force getting the value to wait until the asynchronous function is done you can do this.

async renderButton(){
   await renderShadowDomButton(); 
   const globalValue = getGlobalValue()
}

this should solve your problem and stop the execution until the async call is done.

CodePudding user response:

Moving from async/await to .then() doesn't magically change the asynchronous nature of the code to synchronous. The call to .then() is non-blocking, meaning you only set up a callback. You want to set the callback up and then wait for it to complete before moving to the next statement. That's not going to happen.

I could give you some variant here and there, but they will just be some "clever" use of promises. Stick with asynchronous programming all the way and all will be fine. NodeJS and the browsers now fully support async programming, including top-level await's.

  • Related