* Wait for a DOM element to appear. * @param {string} selector - CSS selector * @param {number} timeout - Max wait time in ms (default 10000) * @returns {Promise }
(selector, timeout = 10000)
| 63 | * @returns {Promise<Element>} |
| 64 | */ |
| 65 | function waitForElement(selector, timeout = 10000) { |
| 66 | return new Promise((resolve, reject) => { |
| 67 | throwIfStopped(); |
| 68 | |
| 69 | const existing = document.querySelector(selector); |
| 70 | if (existing) { |
| 71 | console.log(LOG_PREFIX, `立即找到元素: ${selector}`); |
| 72 | log(`已找到元素:${selector}`); |
| 73 | resolve(existing); |
| 74 | return; |
| 75 | } |
| 76 | |
| 77 | console.log(LOG_PREFIX, `等待元素: ${selector}(超时 ${timeout}ms)`); |
| 78 | log(`正在等待选择器:${selector}...`); |
| 79 | |
| 80 | let settled = false; |
| 81 | let stopTimer = null; |
| 82 | const cleanup = () => { |
| 83 | if (settled) return; |
| 84 | settled = true; |
| 85 | observer.disconnect(); |
| 86 | clearTimeout(timer); |
| 87 | clearTimeout(stopTimer); |
| 88 | }; |
| 89 | |
| 90 | const observer = new MutationObserver(() => { |
| 91 | if (flowStopped) { |
| 92 | cleanup(); |
| 93 | reject(new Error(STOP_ERROR_MESSAGE)); |
| 94 | return; |
| 95 | } |
| 96 | const el = document.querySelector(selector); |
| 97 | if (el) { |
| 98 | cleanup(); |
| 99 | console.log(LOG_PREFIX, `等待后找到元素: ${selector}`); |
| 100 | log(`已找到元素:${selector}`); |
| 101 | resolve(el); |
| 102 | } |
| 103 | }); |
| 104 | |
| 105 | observer.observe(document.body || document.documentElement, { |
| 106 | childList: true, |
| 107 | subtree: true, |
| 108 | }); |
| 109 | |
| 110 | const timer = setTimeout(() => { |
| 111 | cleanup(); |
| 112 | const msg = `在 ${location.href} 等待 ${selector} 超时,已超过 ${timeout}ms`; |
| 113 | console.error(LOG_PREFIX, msg); |
| 114 | reject(new Error(msg)); |
| 115 | }, timeout); |
| 116 | |
| 117 | const pollStop = () => { |
| 118 | if (settled) return; |
| 119 | if (flowStopped) { |
| 120 | cleanup(); |
| 121 | reject(new Error(STOP_ERROR_MESSAGE)); |
| 122 | return; |
no test coverage detected