Google Identity Services异步Promise未等待resolve问题求助
问题描述
我在使用Google Identity Services搭建网页登录功能时遇到了问题:编写的async函数connectOAuth调用相关API后,其.then()方法会在Promise实际完成前提前执行。目前只能用setTimeout临时延迟关闭加载屏,但这并非合理方案,导致加载屏提前关闭破坏了网页整体CSS样式。
代码示例
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)) }, [])
解决方案
核心问题在于google.accounts.id.initialize、renderButton、prompt这些方法并不返回Promise,你用await无法真正等待它们的操作完成,导致connectOAuth函数直接进入resolved状态,.then()因此提前触发。同时你之前的.then()写法有误:.then(setTimeout(...))会立即执行setTimeout,而非等待Promise完成后执行。
正确实现方式:用Promise封装异步操作
把Google Identity Services的方法封装成Promise,确保await能等待操作完成:
const connectOAuth = async () => { /* global google */ // 封装initialize:本身是同步操作,直接resolve确保后续操作依赖其状态 await new Promise(resolve => { google.accounts.id.initialize({ client_id: "133396583135-1rar9q7nq2fotg5h6qk085i97s37hi5u.apps.googleusercontent.com", callback: handleCallBackResponse }); resolve(); }); // 封装renderButton:用requestAnimationFrame确保DOM渲染完成后再执行下一步 await new Promise(resolve => { google.accounts.id.renderButton(document.getElementById("loginButton"), {theme: "outline", size: "large"}); requestAnimationFrame(resolve); }); // 封装prompt:利用其回调函数等待提示框状态稳定后resolve await new Promise(resolve => { google.accounts.id.prompt((notification) => { // 提示框显示/跳过/未显示时都视为操作完成 if (notification.isNotDisplayed() || notification.isSkippedMoment() || notification.isDisplayed()) { resolve(); } }); }); }; useEffect(() => { connectOAuth().then(() => { setLoading(false); // 直接在Promise完成后关闭加载屏,无需setTimeout }); }, []);
关键细节说明
initialize是同步操作,但封装成Promise能保证后续操作在其配置完成后执行。renderButton虽同步修改DOM,但requestAnimationFrame能等待浏览器完成重绘,确保按钮渲染就绪。prompt的回调会在提示框状态变化时触发,通过判断状态来resolve Promise,保证等待到提示框相关操作完成。
内容的提问来源于stack exchange,提问作者Vivek Y V
相关产品推荐
相关产品推荐

