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

Playwright报错‘Execution context was destroyed’问题排查与优化咨询

问题:Playwright封装循环函数后触发"Execution context was destroyed"错误

我给Playwright脚本写了个辅助函数loopOverLocators,想简化嵌套循环的写法和可读性,但现在碰到了错误:Execution context was destroyed, most likely because of a navigation。已经用了async/await,但搞不懂为什么导航会在代码执行前触发。手动写循环逻辑能正常跑,封装成函数就出问题。另外也想听听对这段代码和实现思路的改进建议。


辅助函数代码

loopOverLocators: async (locator, callback) => {
        for (let i = 0; i < await locator.count(); i++) 
        {
            callback(locator.nth(i))
        }
    }

主文件代码

import { test, expect } from "@playwright/test";
import fs from 'fs'
import path from 'path'
import dotenv from 'dotenv'
dotenv.config({ override: true })
import { createOutputFile, getInputFromHeader, loopOverLocators } from '../helpers/utils'
import paths from '../get-paths'

const USERNAME = process.env.USERNAME
const PASSWORD = process.env.PASSWORD

const filename = "all-test-entities.csv"
const headers = JSON.parse(fs.readFileSync(path.join(paths.helpers_dir, 'get-headers.json'), 'utf-8'))
const countries = JSON.parse(fs.readFileSync(path.join(paths.helpers_dir, 'get-countries.json'), 'utf-8'))
const file = createOutputFile(filename)

test("Output all test entities to CSV file", async ({ page }) => {

    let test_entities = []

    await page.goto('https://adminportal.trulioo.com/Account/LogOn');
    await page.locator('#UserName').click();
    await page.locator('#UserName').fill(USERNAME);
    await page.locator('#Password').click();
    await page.locator('#Password').fill(PASSWORD);
    await page.getByRole('button', { name: 'Sign In' }).click();
    await page.frameLocator('#duo_iframe').getByRole('button', { name: 'Send Me a Push' }).click();

    await page.getByRole('link', { name: 'Admin Portal' }).click();
    await page.getByRole('link', { name: 'Global', exact: true }).click();
    await page.getByRole('link', { name: 'Manage Default Test Entities' }).click();

    for (const country_option of countries.options)
    {
        console.log("Entered " + country_option)
        await page.locator('#SelectedConfiguration').selectOption(country_option);
        await page.getByRole('button', { name: 'View Test Entities' }).click();
        await page.waitForSelector('.default-test-entity')

        // loop over `.default-test-entity locators`
        const test_entity_locators = page.locator('.default-test-entity')
        loopOverLocators(test_entity_locators, async (test_entity) => {
            console.log(await test_entity)
        })
    }
})

报错信息

Error: locator.count: Execution context was destroyed, most likely because of a navigation

       at ..\helpers\utils.js:38

      36 |     },
      37 |     loopOverLocators: async (locator, callback) => {
    > 38 |         for (let i = 0; i < await locator.count(); i++)
         |                                           ^
      39 |         {
      40 |             callback(locator.nth(i))
      41 |         }

        at loopOverLocators (C:\Development\create-test-entities\helpers\utils.js:38:43)

错误原因与修复方案

核心问题

  1. 异步回调未等待:loopOverLocators调用异步回调时没有加await,导致函数直接跳过回调执行,外层国家循环会提前触发下一次导航(切换国家后点击View Test Entities),此时之前的页面上下文被销毁,未完成的locator.count查询就会报错。
  2. 调用函数未加await:主代码中调用loopOverLocators时也没有加await,进一步加剧了异步执行的混乱。

修复后的辅助函数

loopOverLocators: async (locator, callback) => {
    // 提前获取count,避免循环中重复查询
    const count = await locator.count();
    for (let i = 0; i < count; i++) {
        // 等待异步回调执行完成
        await callback(locator.nth(i));
    }
}

修复后的调用代码

// 加上await等待整个循环完成
await loopOverLocators(test_entity_locators, async (test_entity) => {
    // 建议获取具体属性,直接打印locator无实际意义
    console.log(await test_entity.textContent());
})

额外改进建议

  1. 使用Playwright内置遍历方法:Locator本身支持each()方法,无需自己封装循环,代码更简洁且符合官方最佳实践:
    await test_entity_locators.each(async (test_entity) => {
        // 处理每个元素逻辑
    });
    
  2. 移除冗余等待:Playwright的Locator默认会自动等待元素可见/可交互,无需额外调用waitForSelector,可以直接使用page.locator('.default-test-entity')。
  3. 错误处理:在循环逻辑中加入try/catch,避免单个元素处理失败导致整个脚本崩溃。
  4. 资源清理:测试结束后记得关闭创建的文件流,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 03:27:46