以下内容就是复制的,好多地方没理解。也就不便注释了。待我内力大增时再来消化。
此例子经常会运行不成功,显示错误信息: attempting to access detached ArrayBuffer(试图访问分离的ArrayBuffer )。错误位于go代码ctx.SetImageToHueCb.Invoke(ptr, len(bs))。多次运行发现:一般一百多K的图片,刷新浏览器即选择运行就没问题,第二次运行亦出错。超过一百K太多,随便运行都出错。
####内存访问
除了函数调用的交互,还可以通过内存直接共享数据。
Golang 端使用的内存空间,通过 instance.exports.mem 暴露给 JS 端,这里 instance 为 WebAssembly.instantiate* 函数实例化 wasm 模块得到的 instance。可以通过 mem 创建 TypedArray,以此在 JS 直接读写 Golang 使用的内存。
下面的例子会在 JS 端打开一个图片文件,显示在页面上,并将文件内容直接写入 Golang 使用的内存,在 Golang 中将图片的色调改变,再回调 JS 端来读取改变之后的图片,并显示在页面上。
package main
import (
"bytes"
"image"
"reflect"
"sync"
"syscall/js"
"unsafe"
"github.com/anthonynsimon/bild/adjust"
"github.com/anthonynsimon/bild/imgio"
)
type Ctx struct {
SetFileArrCb js.Value
SetImageToHueCb js.Value
}
func setFile(ctx *Ctx, fileJsArr js.Value, length int) {
bs := make([]byte, length)
ptr := (*reflect.SliceHeader)(unsafe.Pointer(&bs)).Data
ctx.SetFileArrCb.Invoke(fileJsArr, ptr)
img, _, _ := image.Decode(bytes.NewReader(bs))
buf := &bytes.Buffer{}
imgio.JPEGEncoder(93)(buf, adjust.Hue(img, -150))
bs = buf.Bytes()
ptr = (*reflect.SliceHeader)(unsafe.Pointer(&bs)).Data
ctx.SetImageToHueCb.Invoke(ptr, len(bs))
}
func main() {
jsGlobal := js.Global()
ctx := &Ctx{
SetFileArrCb: jsGlobal.Get("setFileArrCb"),
SetImageToHueCb: jsGlobal.Get("setImageToHueCb"),
}
goFuncs := jsGlobal.Get("goFuncs")
goFuncs.Set("setFile", js.FuncOf(func(this js.Value,args []js.Value) interface{} {
setFile(ctx, args[0], args[1].Int())
return nil
}))
wg := &sync.WaitGroup{}
wg.Add(1)
wg.Wait()
}
<html>
<head>
<meta charset="utf-8">
<script src="wasm_exec.js"></script>
<script>
let goMemArr, fileType
let setImageToElem = (elemId, dateArr) => {
document.getElementById(elemId).src = URL.createObjectURL(
new Blob([dateArr], {"type": fileType}))
}
window.setFileArrCb = (fileArr, ptr) => {
goMemArr.set(fileArr, ptr)
}
window.setImageToHueCb = (ptr, len) => {
setImageToElem("img-hue", goMemArr.slice(ptr, ptr + len))
}
window.goFuncs = {}
const go = new Go()
WebAssembly.instantiateStreaming(fetch("go_main.wasm"), go.importObject).
then(res => {
goMemArr = new Uint8Array(res.instance.exports.mem.buffer)
go.run(res.instance)
}
)
let onFileSelected = event => {
let reader = new FileReader()
let file = event.target.files[0]
fileType = file.type
reader.onload = event => {
let fileArr = new Uint8Array(event.target.result)
setImageToElem("img-ori", fileArr)
window.goFuncs.setFile(fileArr, fileArr.length)
}
reader.readAsArrayBuffer(file)
}
window.onload = () => {
document.getElementById("file-input").addEventListener("change", onFileSelected)
}
</script>
</head>
<body>
<input id="file-input" type="file" />
<br />
<image id="img-ori" />
<br />
<image id="img-hue" />
</body>
</html>
在html中,涉及到一些ES6(ECMAScript 6.0)等标准的语法不是太明白,看来也需要学习。
ES6 2015 -> ES7 2016 -> ES8 2018 -> ES9 2018 -> ES10 2019
看看这个生产线,好象错过了几个亿…..
fetch 发起异步请求
//ES5 $(’#bt’).click(function (e) { //doing something }) //ES6 $(’#bt’).click(e => { //doing something })