如何用Vanilla JS实现原生prompt函数的同步返回效果?
解决自定义Prompt返回undefined的问题
嘿,我懂你遇到的麻烦了——原生的prompt()是阻塞式的函数,它会暂停整个JS线程直到用户完成输入,所以你能直接拿到返回值。但咱们用DOM元素手动实现的自定义prompt是异步的,myPrompt函数会在创建完DOM元素后立刻返回,根本等不到用户点击OK按钮,这就是为什么receiveResult里的alert(result)拿到的是undefined。
解决方案:用Promise包装异步交互
要解决这个问题,我们需要把用户的点击操作变成一个异步等待的过程,这里用Promise是最合适的。我们让myPrompt返回一个Promise,当用户点击OK按钮时,再用resolve把输入的值传递出去。
修改后的完整代码:
function myPrompt(message) { // 返回一个Promise,等待用户交互完成 return new Promise((resolve) => { var wrap = document.createElement('div'); wrap.setAttribute("id", "wrap"); var input = document.createElement('input'); input.setAttribute("id","input"); input.setAttribute("type","text"); var button = document.createElement('button'); button.setAttribute("id","button"); button.innerHTML = "OK"; button.onclick = function() { const result = input.value; // 直接用变量更简洁,不用重复获取DOM元素 wrap.remove(); // 直接移除创建的弹窗容器 resolve(result); // 把用户输入的结果传递给Promise的回调 } wrap.innerHTML = message; wrap.appendChild(input); wrap.appendChild(button); document.body.appendChild(wrap); }); } // 用async/await等待Promise完成,拿到输入结果 async function receiveResult() { var result = await myPrompt("Say Hi!!"); alert(result); } // 如果你不想用async/await,也可以用.then()写法: // function receiveResult() { // myPrompt("Say Hi!!").then(result => { // alert(result); // }); // }
#wrap { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 1rem; background: yellow; display: flex; gap: 0.5rem; align-items: center; }
<button onclick="receiveResult()">Show My Prompt</button>
为什么这样能行?
myPrompt现在返回一个Promise对象,这个对象会暂时处于pending状态,直到用户点击OK按钮触发后续逻辑。- 当用户点击按钮时,我们调用
resolve(result)把输入的值传递出去,Promise的状态会切换为fulfilled。 receiveResult用await(或者.then())等待Promise完成,这样就不会在用户输入前执行alert,而是拿到真正的输入值后再弹出提示。
另外我还优化了代码细节:直接用创建元素时的变量input和wrap,不用再通过getElementById重复获取,代码更简洁高效。
内容的提问来源于stack exchange,提问作者Marcelo Barganha
相关产品推荐
相关产品推荐

