如何检查调试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无侵入调试
- 断点停在
await Promise.all(...)行时,在作用域面板找到g.get(order).map(loadScript)生成的Promise数组,右键选择「Store as global variable」,控制台会自动生成类似temp1的全局变量指向该数组。 - 在控制台执行以下代码,批量输出所有Promise的状态:
控制台输出的表格会直接列出每个Promise的状态,对应数组索引即可找到异常的script节点。Promise.allSettled(temp1).then(results => { console.table(results.map((res, index) => ({ arrayIndex: index, status: res.status, result: res.value ?? res.reason }))) }) - 也可以直接打开Network面板筛选JS类型请求,核对哪些
data-src对应的请求根本未发起,对应的就是未触发加载流程的script节点。
- 断点停在
内容的提问来源于stack exchange,提问作者philolegein
相关产品推荐
相关产品推荐

