Playwright TypeScript中用Promise.race()等待二选一元素的问题
一、Promise.race()使用错误导致变量值异常
你对Promise.race()的用法理解有误:Promise.race()仅返回第一个完成的Promise的结果,并非数组。你用const [failed, validated] = await Promise.race(...)的解构赋值,本质是把返回的字符串(比如"Passed")拆成单个字符,这就是为什么会得到"E"、"C"这类无意义值的原因。
修正后的基础代码
public waitForFinalStatus = async (): Promise<boolean> => { const result = await Promise.race([ this.locFailed().waitFor({ timeout: 120000 }).then(() => "Failed"), this.locValidated().waitFor({ timeout: 120000 }).then(() => "Passed") ]); return result === "Passed"; }
不过这段代码还有隐藏问题:未完成的waitFor会在超时后抛出错误,接下来详细说明这个问题。
二、Playwright waitFor的异常处理与行为差异
超时是否会抛错?
是的,Playwright的waitFor如果在指定超时时间内未满足条件(比如目标元素未出现),会直接抛出TimeoutError。即使其中一个元素已被找到,另一个waitFor仍会在后台继续等待,直到超时后抛出错误——若未捕获该错误,会触发未处理的Promise拒绝,可能中断整个程序流程。和Selenium WebDriverWait的区别
Selenium的WebDriverWait内部会自动忽略NotFoundException这类元素不存在的异常,仅关注目标条件是否达成。但Playwright的waitFor没有此机制,任何失败(包括超时)都会抛出异常,必须手动处理。正确的异常处理方式
给每个waitFor添加catch逻辑,让超时的Promise返回一个标识值(比如null),这样即使超时也不会导致整个Promise.race被拒绝:
public waitForFinalStatus = async (): Promise<boolean> => { const result = await Promise.race([ this.locFailed().waitFor({ timeout: 120000 }) .then(() => "Failed") .catch(() => null), // 捕获超时/未找到的异常,返回null this.locValidated().waitFor({ timeout: 120000 }) .then(() => "Passed") .catch(() => null) ]); // 处理两个元素都超时的情况 if (!result) { throw new Error("等待状态超时,未找到Validated或Failed元素"); } return result === "Passed"; }
这样,当其中一个元素出现时,Promise.race会立即返回对应结果,另一个超时的Promise会被catch处理,不会抛出未捕获的异常。
内容的提问来源于stack exchange,提问作者Ahamed Abdul Rahman

