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

如何检查调试Promise.all中单个Promise的状态定位异常项

问题场景

实现批量加载script标签的逻辑:将不带src属性的script节点转换为Promise数组,转换规则为:

  • 读取节点的data-src属性值,设置为节点的src属性
  • 给节点绑定onload事件,触发时执行resolve
  • 给节点绑定onerror事件,触发时执行reject
    所有同批次Promise用Promise.all包裹后await等待执行,按顺序递归加载下一批次脚本,但程序始终卡在Promise.all的等待阶段无法向下执行。已知部分Promise已经完成状态流转,但无法定位哪些Promise始终停留在pending状态。
    对应实现代码如下:
function loadScript (script) {
  return new Promise(function(resolve, reject) {
    // this happens for every script
    script.setAttribute("src", script.getAttribute("data-src"));
    script.onload = _ => resolve(script.src);
    script.onerror = _ => reject(script.src);
  });
}

// loadScripts : (graph, int) -> (string array) promise
async function loadScripts(g, order = 1) {
  if (!g.has(order))
    return []
  else
    return [
      ...await Promise.all(g.get(order).map(loadScript)),
      // the script stops here after the first pass and never executes the
      // next line. It just ... awaits the previous line
      ...await loadScripts(g, order + 1)
    ]
}

目前通过Chrome DevTools断点单步调试到卡顿位置,不清楚await等待阶段如何查看单个Promise的状态,区分已完成状态敲定、仍处于pending的Promise。

排查方案
  • 临时埋点定位(最直接)
    在全局定义调试数组,修改loadScript方法记录每个脚本的加载状态,卡顿时直接在控制台过滤pending项即可。

    // 临时调试用全局变量,排查完成后删除即可
    window.__scriptLoadDebugList = []
    function loadScript (script) {
      const debugRecord = {
        targetSrc: script.getAttribute('data-src'),
        status: 'pending',
        node: script
      }
      window.__scriptLoadDebugList.push(debugRecord)
      return new Promise(function(resolve, reject) {
        script.setAttribute("src", script.getAttribute("data-src"));
        script.onload = _ => {
          debugRecord.status = 'fulfilled'
          resolve(script.src)
        };
        script.onerror = _ => {
          debugRecord.status = 'rejected'
          reject(script.src)
        };
      });
    }
    

    代码卡住时在控制台执行window.__scriptLoadDebugList.filter(item => item.status === 'pending'),即可拿到所有未完成状态流转的script节点。

    注意:script标签仅设置src但未插入DOM树时,不会触发资源加载,自然永远不会执行onload/onerror回调,这是这类问题最高发的根因。

  • DevTools无侵入调试

    1. 断点停在await Promise.all(...)行时,在作用域面板找到g.get(order).map(loadScript)生成的Promise数组,右键选择「Store as global variable」,控制台会自动生成类似temp1的全局变量指向该数组。
    2. 在控制台执行以下代码,批量输出所有Promise的状态:
      Promise.allSettled(temp1).then(results => {
        console.table(results.map((res, index) => ({
          arrayIndex: index,
          status: res.status,
          result: res.value ?? res.reason
        })))
      })
      
      控制台输出的表格会直接列出每个Promise的状态,对应数组索引即可找到异常的script节点。
    3. 也可以直接打开Network面板筛选JS类型请求,核对哪些data-src对应的请求根本未发起,对应的就是未触发加载流程的script节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:30:52