You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebView2应用调用JavaScript的async/await时出现冻结问题求助

WebView2中使用showModalDialog Polyfill导致应用冻结的解决方案

问题概述

基于Microsoft WebView2的嵌入式Web应用,在执行含await的showModalDialog polyfill代码时,整个应用完全冻结,无法响应任何输入;但相同代码在Edge/Chrome浏览器中运行正常。使用的polyfill基于MDN提供的实现,测试代码通过await调用该polyfill获取模态框返回值。

核心原因

WebView2的渲染线程与宿主应用的UI主线程存在绑定关系,原生<dialog>的showModal()方法在WebView2环境中会触发特殊的模态阻塞逻辑——不同于普通浏览器仅阻塞页面内的JS执行,WebView2会将这种阻塞传导至宿主应用的主线程,导致整个应用失去响应。而浏览器环境中,<dialog>的模态仅限制页面内交互,不会影响浏览器本身的消息循环。

修复方案

方案1:替换原生<dialog>为自定义模态实现

放弃使用原生<dialog>元素,改用CSS实现模态遮罩,配合异步逻辑实现相同功能,避免触发WebView2的主线程阻塞:

修改后的polyfill代码:

window.showModalDialog = window.showModalDialog || function(url, arg, opt) {
  url = url || '';
  arg = arg || null;
  opt = opt || 'dialogWidth:300px;dialogHeight:200px';

  // 解析模态框样式参数
  const styleObj = {};
  opt.split(';').forEach(item => {
    const [key, val] = item.trim().split(':');
    if (key && val) {
      styleObj[key.replace(/dialog/gi, '')] = val;
    }
  });

  // 创建全屏模态遮罩
  const overlay = document.createElement('div');
  overlay.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0,0,0,0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
  `;

  // 创建模态框容器
  const dialogContainer = document.createElement('div');
  Object.keys(styleObj).forEach(key => {
    dialogContainer.style[key] = styleObj[key];
  });
  dialogContainer.style.cssText += `
    position: relative;
    background: white;
    border-radius: 4px;
    overflow: hidden;
  `;

  // 插入关闭按钮与iframe内容
  dialogContainer.innerHTML = `
    <a href="#" id="dialog-close" style="position: absolute; top: 0; right: 5px; font-size: 20px; color: #000; text-decoration: none; outline: none; padding: 5px;">&times;</a>
    <iframe id="dialog-body" src="${url}" style="border: 0; width: 100%; height: 100%;"></iframe>
  `;

  overlay.appendChild(dialogContainer);
  document.body.appendChild(overlay);

  const iframe = document.getElementById('dialog-body');
  iframe.contentWindow.dialogArguments = arg;

  // 封装关闭逻辑
  return new Promise((resolve) => {
    const closeHandler = () => {
      overlay.remove();
      resolve(iframe.contentWindow.returnValue);
    };

    // 绑定关闭按钮事件
    document.getElementById('dialog-close').addEventListener('click', e => {
      e.preventDefault();
      closeHandler();
    });

    // 支持iframe内部主动关闭模态框(可选)
    iframe.contentWindow.addEventListener('message', (e) => {
      if (e.data === 'closeModal') {
        closeHandler();
      }
    });
  });
};

方案2:升级WebView2 Runtime至最新版本

部分旧版本WebView2存在<dialog>元素的模态阻塞bug,升级到最新稳定版可解决该问题。可通过宿主应用自动更新WebView2 Runtime,或引导用户手动安装。

方案3:调整宿主应用的消息循环处理

确保宿主应用的主线程消息循环不会被WebView2的回调阻塞,避免在同步回调中执行耗时操作,保证UI线程能及时处理用户输入事件。

测试验证

使用修改后的polyfill代码,测试await window.showModalDialog(...)逻辑,应用将不再冻结,模态框可正常交互,关闭后能正确获取返回值。

内容的提问来源于stack exchange,提问作者RISHAB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:24:53