Golang中chromedp.Poll与PollFunction的使用方法

Golang中chromedp.Poll与PollFunction的使用方法 我正在评估JavaScript以确定页面是否完全加载。我目前正在使用chromedp.Evaluate,并发现使用chromedp.Poll或chromedp.PollFunction函数可以减少代码量。

然而,我尝试了这两种方法都没有成功:

const ( pollFunction = ` function isInitialized(logMessage) { if(typeof globalThis.logger === ‘undefined’) { console.log(‘logger is undefined’); return false; }

console.log(‘checking logs’); return globalThis.logger.dump().some(log => typeof log === ‘string’ && log.includes(logMessage));

} `

pollStatement = typeof globalThis.logger !== 'undefined' && globalThis.logger.dump().some(log => typeof log === 'string' && log.includes('%s')) )

这会导致超时:

chromedp.Run(ctx, chromedp.Poll(fmt.Sprintf(pollStatement, logMessage), nil, chromedp.WithPollingArgs(logMessage), chromedp.WithPollingInterval(pollInterval), chromedp.WithPollingTimeout(pollTimeout)))

我尝试了函数和内联语句两种方式。使用函数时,我希望能看到一些语句打印到控制台,但什么也没有得到。

虽然我使用Evaluate的版本可以工作,但我需要自己进行轮询。如果有更好的方法,我希望使用它。

Poll和PollFunction的参考资料:puppeteer/docs/api.md at v8.0.0 · puppeteer/puppeteer · GitHub,并且我已经尝试了各种语法变体,以查看是否是语法错误。


更多关于Golang中chromedp.Poll与PollFunction的使用方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我想我已经解决了这个问题,我传入了错误的上下文。上面的代码仍然是正确的,但那是在一个函数中,并且该函数被错误地调用了。

我传入了原始的上下文,该上下文的时间限制是5秒,但它启动得更早,而我等待的那个真值大约需要10秒才能返回,这就是它从未成功的原因。

更多关于Golang中chromedp.Poll与PollFunction的使用方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在chromedp中使用PollPollFunction时,需要注意JavaScript执行上下文和参数传递的正确方式。以下是两种方法的具体实现:

1. 使用PollFunction的正确方式

// 定义JavaScript函数
const pollFunction = `
function isInitialized(logMessage) {
    if (typeof globalThis.logger === 'undefined') {
        console.log('logger is undefined');
        return false;
    }
    
    console.log('checking logs for:', logMessage);
    const logs = globalThis.logger.dump();
    return logs.some(log => typeof log === 'string' && log.includes(logMessage));
}
`

func waitForLogMessage(ctx context.Context, logMessage string) error {
    return chromedp.Run(ctx,
        chromedp.PollFunction(
            pollFunction,
            func(result *runtime.RemoteObject) bool {
                if result.Type == "boolean" && result.Value == true {
                    return true
                }
                return false
            },
            chromedp.WithPollingArgs(logMessage),
            chromedp.WithPollingInterval(1*time.Second),
            chromedp.WithPollingTimeout(30*time.Second),
        ),
    )
}

2. 使用Poll的正确方式

func waitForLogMessagePoll(ctx context.Context, logMessage string) error {
    // 使用模板字符串避免注入问题
    pollStatement := `
    (function(logMessage) {
        if (typeof globalThis.logger === 'undefined') {
            console.log('logger is undefined');
            return false;
        }
        
        const logs = globalThis.logger.dump();
        return logs.some(log => typeof log === 'string' && log.includes(logMessage));
    })("%s")
    `
    
    return chromedp.Run(ctx,
        chromedp.Poll(
            fmt.Sprintf(pollStatement, logMessage),
            nil,
            chromedp.WithPollingInterval(1*time.Second),
            chromedp.WithPollingTimeout(30*time.Second),
        ),
    )
}

3. 更简洁的PollFunction示例

func waitForElementReady(ctx context.Context) error {
    return chromedp.Run(ctx,
        chromedp.PollFunction(
            `() => {
                const element = document.querySelector('#myElement');
                if (!element) return false;
                return element.offsetWidth > 0 && element.offsetHeight > 0;
            }`,
            func(result *runtime.RemoteObject) bool {
                return result.Type == "boolean" && result.Value == true
            },
            chromedp.WithPollingInterval(500*time.Millisecond),
            chromedp.WithPollingTimeout(10*time.Second),
        ),
    )
}

4. 带参数的PollFunction示例

func waitForSpecificText(ctx context.Context, selector, expectedText string) error {
    return chromedp.Run(ctx,
        chromedp.PollFunction(
            `(selector, expectedText) => {
                const element = document.querySelector(selector);
                if (!element) return false;
                return element.textContent.includes(expectedText);
            }`,
            func(result *runtime.RemoteObject) bool {
                return result.Type == "boolean" && result.Value == true
            },
            chromedp.WithPollingArgs(selector, expectedText),
            chromedp.WithPollingInterval(1*time.Second),
            chromedp.WithPollingTimeout(20*time.Second),
        ),
    )
}

5. 调试版本(添加日志输出)

func waitForLogMessageDebug(ctx context.Context, logMessage string) error {
    debugFunction := `
    function checkLogs(logMessage) {
        console.log('PollFunction called with message:', logMessage);
        
        if (typeof globalThis.logger === 'undefined') {
            console.log('DEBUG: logger is undefined');
            return false;
        }
        
        console.log('DEBUG: logger exists, checking logs...');
        const logs = globalThis.logger.dump();
        console.log('DEBUG: logs count:', logs.length);
        
        const found = logs.some(log => {
            if (typeof log === 'string') {
                const includes = log.includes(logMessage);
                if (includes) console.log('DEBUG: Found matching log:', log);
                return includes;
            }
            return false;
        });
        
        console.log('DEBUG: result:', found);
        return found;
    }
    `
    
    return chromedp.Run(ctx,
        chromedp.PollFunction(
            debugFunction,
            func(result *runtime.RemoteObject) bool {
                fmt.Printf("Go received result: Type=%s, Value=%v\n", 
                    result.Type, result.Value)
                return result.Type == "boolean" && result.Value == true
            },
            chromedp.WithPollingArgs(logMessage),
            chromedp.WithPollingInterval(2*time.Second),
            chromedp.WithPollingTimeout(60*time.Second),
        ),
    )
}

关键点:

  1. PollFunction需要返回一个函数,而不是函数定义字符串
  2. 参数通过WithPollingArgs传递,在JavaScript函数中作为参数接收
  3. Poll直接执行JavaScript表达式,需要返回布尔值
  4. 确保JavaScript代码在浏览器上下文中能正确执行
  5. 使用适当的轮询间隔和超时时间
回到顶部