如何将headless_chrome页面加载回调转为可await表达式以等待页面加载
如何在Rust的headless_chrome中等待页面完全加载后执行截图?
我需要用headless_chrome crate对网页进行截图,要求等页面所有资源(包括CSS、字体等)完全加载完成后再执行截图。根据官方文档,可以通过监听PageLoadEventFired事件来捕获页面加载完成的时机,但官方给出的示例是回调形式,无法转换成可await的表达式,没法让后续代码仅在页面加载完成后运行——类似JavaScript中用Promise监听load事件的实现:
const waitForPageLoad = () => { return new Promise((resolve) => { window.addEventListener("load", resolve) }) } await waitForPageLoad()
解决方案:用tokio::sync::oneshot实现异步等待
在Rust中,可以借助tokio::sync::oneshot单消息通道,将事件回调的信号转换成可await的操作,实现等待页面加载完成后再执行后续代码的效果。
完整代码示例:
use headless_chrome::{Browser, tab::Event}; use tokio::sync::oneshot; use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // 初始化浏览器和标签页 let browser = Browser::default()?; let tab = browser.new_tab()?; // 创建单消息通道,用于传递页面加载完成的信号 let (sender, receiver) = oneshot::channel(); // 注册页面加载完成事件监听器 tab.add_event_listener(Arc::new(move |event: &Event| { if let Event::PageLoadEventFired(_) = event { // 发送加载完成信号,忽略发送失败的情况(如接收器已被丢弃) let _ = sender.send(()); } }))?; // 导航到目标网页 tab.navigate_to("https://example.com")?; // 等待页面加载完成的信号 receiver.await?; // 页面加载完成,执行截图操作 let screenshot = tab.capture_screenshot( headless_chrome::protocol::page::ScreenshotFormat::Png, None, None, true )?; std::fs::write("screenshot.png", screenshot)?; Ok(()) }
代码说明
- oneshot通道:
oneshot::channel()创建一对发送器(sender)和接收器(receiver),接收器可以通过await阻塞,直到发送器发送消息。 - 事件监听:将发送器移入事件监听的闭包中,当捕获到
PageLoadEventFired事件时,发送空信号()。 - 顺序注意:必须先注册事件监听器,再执行页面导航,避免错过页面加载完成的事件。
- 错误处理:忽略发送信号的错误,因为如果接收器已经被丢弃(比如程序提前终止),发送操作没有实际意义。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

