OnLoadData 同步,异步,分开加载数据
2024-07-09 16:19:39
设置回调函数代码:
// setup asset routes win.SetCallback(&sciter.CallbackHandler{ OnLoadData: func(params *sciter.ScnLoadData) int { return customOnLoadData(params) }, })
回调函数代码如下:
func customOnLoadData(params *sciter.ScnLoadData) int { // 定义自定义的 OnLoadData 函数,参数是 Sciter 的 ScnLoadData 结构体指针 rq := sciter.WrapRequest(params.RequestId()) // 获取请求的接口,通过请求 ID 获取一个新的 Request 接口 uri, _ := rq.Url() // 获取请求的 URL rqType, _ := rq.RequestType() // 获取请求类型,例如 GET 请求 rqDataType, _ := rq.RequestedDataType() // 获取请求的数据类型,例如 IMAGE 类型 if strings.HasPrefix(uri, "sync://") && rqType == sciter.RRT_GET && rqDataType == sciter.RT_DATA_IMAGE { // 如果 URI 以 "sync://" 开头,并且请求类型是 GET,请求的数据类型是 IMAGE path := uri[7:] // 获取 "sync://" 之后的文件路径 f, err := os.Open(path) // 打开指定路径的文件 if err != nil { // 如果文件打开失败 return sciter.LOAD_DISCARD // 返回 LOAD_DISCARD 表示丢弃这个加载请求 } data, err := ioutil.ReadAll(f) // 读取文件中的所有数据 if err != nil { // 如果读取文件数据失败 return sciter.LOAD_DISCARD // 返回 LOAD_DISCARD 表示丢弃这个加载请求 } rq.SetSucceeded(200, data) // 请求成功,设置 HTTP 状态码 200 和读取的数据 } else if strings.HasPrefix(uri, "async://") && rqType == sciter.RRT_GET && rqDataType == sciter.RT_DATA_IMAGE { // 如果 URI 以 "async://" 开头,并且请求类型是 GET,请求的数据类型是 IMAGE go func() { // 启动一个新的 goroutine 来异步加载数据 path := uri[8:] // 获取 "async://" 之后的文件路径 f, err := os.Open(path) // 打开指定路径的文件 if err != nil { // 如果文件打开失败 rq.SetFailed(404, nil) // 请求失败,设置 HTTP 状态码 404 return // 结束 goroutine } data, err := ioutil.ReadAll(f) // 读取文件中的所有数据 if err != nil { // 如果读取文件数据失败 rq.SetFailed(500, nil) // 请求失败,设置 HTTP 状态码 500 return // 结束 goroutine } rq.SetSucceeded(200, data) // 请求成功,设置 HTTP 状态码 200 和读取的数据 }() return sciter.LOAD_DELAYED // 返回 LOAD_DELAYED 表示数据会被异步加载 } else if strings.HasPrefix(uri, "chunked://") && rqType == sciter.RRT_GET && rqDataType == sciter.RT_DATA_IMAGE { // 如果 URI 以 "chunked://" 开头,并且请求类型是 GET,请求的数据类型是 IMAGE go func() { // 启动一个新的 goroutine 来异步分块加载数据 path := uri[10:] // 获取 "chunked://" 之后的文件路径 f, err := os.Open(path) // 打开指定路径的文件 if err != nil { // 如果文件打开失败 rq.SetFailed(404, nil) // 请求失败,设置 HTTP 状态码 404 return // 结束 goroutine } buf := make([]byte, 1<<16) // 创建一个 64KB 的缓冲区 for { // 循环读取文件数据 n, err := f.Read(buf) // 读取文件中的数据到缓冲区,返回读取的字节数 rq.AppendDataChunk(buf[:n]) // 将读取到的字节作为数据块追加到请求中 if err == io.EOF { // 如果读取到文件末尾 rq.SetSucceeded(200, nil) // 请求成功,设置 HTTP 状态码 200 return // 结束 goroutine } } }() return sciter.LOAD_DELAYED // 返回 LOAD_DELAYED 表示数据会被异步加载 } return sciter.LOAD_OK // 默认情况下,返回 LOAD_OK 表示数据已经成功加载 }
rq.RequestedDataType() 会有以下几种类型:
这段代码定义了一个枚举类型 SciterResourceType
,用于表示不同类型的资源数据。下面是每个枚举常量的意义解释:
RT_DATA_HTML: HTML 数据类型。表示请求的资源是 HTML 内容。
RT_DATA_IMAGE: 图像数据类型。表示请求的资源是图像。
RT_DATA_STYLE: 样式数据类型。表示请求的资源是样式表(CSS)。
RT_DATA_CURSOR: 光标数据类型。表示请求的资源是光标图标。
RT_DATA_SCRIPT: 脚本数据类型。表示请求的资源是脚本文件(如 JavaScript)。
RT_DATA_RAW: 原始数据类型。表示请求的资源是原始数据,可能是未加工的二进制数据。
RT_DATA_FONT: 字体数据类型。表示请求的资源是字体文件。
RT_DATA_SOUND: 声音数据类型。表示请求的资源是声音文件(如 WAV 格式的音频)。
RT_DATA_FORCE_DWORD: 强制将枚举值转换为 32 位无符号整数。在 C/C++ 中,这种做法有时用于强制枚举类型占用 32 位,但在 Go 中不需要。
这些枚举常量定义了不同种类的资源类型,允许程序根据请求的资源类型采取不同的处理方式,例如在加载数据时区分对待 HTML、图像、样式表等不同类型的资源。