skip to Main Content

I am using Google Identity Services to setup login for my webpage. I am doing API calls in a async function which returns a Promise resolve but the .then function is executed even before the Promise is resolved. I am temporarily managing it with setTimeout but it isnt a good approach right so please help me out in finding the

const connectOAuth = async () => {
    /* global google */
    await google.accounts.id.initialize({
      client_id: "133396583135-1rar9q7nq2fotg5h6qk085i97s37hi5u.apps.googleusercontent.com",
      callback: handleCallBackResponse
    })
    await google.accounts.id.renderButton(document.getElementById("loginButton"), {theme: "outline", size: "large"})
    await google.accounts.id.prompt()
    return Promise.resolve()
  }
  
  useEffect(() => {
    connectOAuth().then(setTimeout(() => {setLoading(false)}, 1000))
  }, [])

error

The loading screen should turn off once API calls are done but it goes off before hand spoiling entire css of my webpage

2

Answers


  1. The posted code is calling setTimeout when evaluating the argument passed to then:

    connectOAuth().then(setTimeout(() => {setLoading(false)}, 1000))
    

    executes

    setTimeout(() => {setLoading(false)}, 1000)
    

    (which starts the timeout) before calling then.

    Now because async functions return a pending promise when they process an await keyword, the then method is called on the promise returned when

    google.accounts.id.initialize
    

    is called, but before initialize has performed any asynchronous work.
    The solution is to register a promise listener, using then, without calling the listener in the process. E.G.

    connectOAuth().then(
      ()=> setTimeout(() => {setLoading(false)}, 1000)
    );
    

    Note that returning promise.resolve() from an async function is superfluous – falling out the bottom of an async function returns undefined which will be used to fulfill the promise returned from calling the async function.

    Login or Signup to reply.
  2. The issue is with your .then() part of the promise chain. The syntax is wrong. The correct syntax for handling promises is:

    somePendingPromise.then(resp => { /* handle the response */ })
    

    So to fix your code, you need to adjust your code like below:

    connectOAuth().then(resp => { 
       console.log(resp);
       setTimeout(() => {setLoading(false)}, 1000);
    })
    

    But if you wish to write a better code, I would recommend you use states for handling all your responses.

    Solution for handling responses using states
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>Hello World</title>
        <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
        <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
        <!-- Don't use this in production: -->
        <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      </head>
      <body>
        <div id="root"></div>
        <script type="text/babel">
        
          function MyApp() {
            const [text, setText] = React.useState('');
            const [isLoading, setIsLoading] = React.useState(false);
          
            const connectOAuth = async () => {
               setIsLoading(true);
               // some delayed task here
               const resp = await fetch("https://hub.dummyapis.com/delay?seconds=2");
               const text = await resp.text();
               
               // then handle the response
               setText(text);
               setIsLoading(false);
            }
    
            React.useEffect(() => {
              connectOAuth();
            }, [])
          
            return (
              <>
                {isLoading ? <span>Loading...</span> : ''} 
                {text && <span>{text}</span>} 
              </>
            )
            
          }
    
          const container = document.getElementById('root');
          const root = ReactDOM.createRoot(container);
          root.render(<MyApp />);
    
        </script>
      </body>
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search