这个例子演示了初始化一个新的浏览器实例,打开 GitHub 首页,并演示如何在等待页面事件时处理上下文取消的情况。
package main
import (
"context"
"fmt"
"time"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/proto"
)
func main() {
browser := rod.New().MustConnect()
defer browser.MustClose()
page := browser.MustPage("https://github.com").MustWaitLoad()
page, cancel := page.WithCancel()
go func() {
time.Sleep(time.Second)
cancel()
}()
// It's a blocking method, it will wait until the context is cancelled
page.EachEvent(func(_ *proto.PageLifecycleEvent) {})()
if page.GetContext().Err() == context.Canceled {
fmt.Println("cancelled")
}
}
前面关于浏览器和页面的相关操作就不再赘述,着重说一下取消上下文的部分。
page, cancel := page.WithCancel()
func (b *Browser) WithCancel() (*Browser, func())
。这是WithCancel()
方法的原型,返回两个返回值,其中page
属于Browser类型的指针,cancel属于一个函数。- 这行代码做的事情
- 创建新的上下文:它复制当前页面对象并关联一个新的可取消的上下文(
context.WithCancel
)。这意味着返回的page
变量现在具有一个与之关联的取消函数。 - 获取取消函数:变量
cancel
是一个函数,当你调用它时,与新page
对象关联的所有操作都将被取消。这对于中断不再需要完成的页面加载或其他长时间运行的任务非常有用。
- 创建新的上下文:它复制当前页面对象并关联一个新的可取消的上下文(
- 这个功能特别适合于以下几种情况:
- 限时操作:如果你有一个页面操作,比如数据抓取或等待元素出现,但你希望在超过特定时间后自动取消这个操作,可以使用
WithCancel
来实现。 - 条件取消:在某些情况下,你可能基于外部事件或条件判断需要中断页面操作。例如,用户取消操作或者程序在其他地方遇到错误需要停止当前操作。
- 限时操作:如果你有一个页面操作,比如数据抓取或等待元素出现,但你希望在超过特定时间后自动取消这个操作,可以使用
go func() {
time.Sleep(time.Second)
cancel()
}()
- 启动一个新的goroutine,其中是一个匿名函数。
- 先调用
time.Sleep(time.Second)
,等待1秒钟,也就是暂停当前goroutine的执行1秒钟。 - 然后调用
cancel()
,这个cancel函数就是上面的page.WithCancel()
获得的,用于取消所有与page相关的挂起操作。
page.EachEvent(func(_ *proto.PageLifecycleEvent) {})()
page.EachEvent(...)
:这是go-rod/rod
库中的一个方法,用于订阅一个或多个特定类型的浏览器事件。在这个上下文中,它用于监听页面的生命周期事件。func(_ \*proto.PageLifecycleEvent) {}
:这是传递给EachEvent
方法的回调函数,用于处理页面生命周期事件。回调函数的参数是指向proto.PageLifecycleEvent
类型的指针,这代表了一个页面生命周期事件。在函数参数列表中的下划线_
表示这个参数在函数体内不会被使用。函数体{}
是空的,意味着当事件发生时,没有任何操作会被执行。- 调用
page.EachEvent(func(_ *proto.PageLifecycleEvent) {})()
会导致代码执行在这里阻塞,等待事件发生。但是,由于回调函数不处理任何事件(因为它的函数体为空),这个调用实际上会一直等待,直到页面的上下文被取消。
if page.GetContext().Err() == context.Canceled {
fmt.Println("cancelled")
}
- 这是在Go(Golang)中处理操作被取消的一种常见模式,通常用于需要提前中止的Web服务器或任何并发操作中。
page.GetContext()
: 这个函数假定是用来获取与page
对象相关联的context.Context
。在Go中,Context用于在API边界和进程之间传递截止日期、取消信号和其他请求范围的值。.Err()
: 这个方法在context.Context
对象上,如果上下文已被取消或超时,则返回一个错误。context.Canceled
: 这是一个预定义的错误,表示上下文被取消了。