SharedArrayBuffer
1.简介
是在浏览器运行的二进制数据缓冲区,也成为共享内存,数据格式类似ArrayBuffer对象。Javascript和WebAssembly可以同时在该内存里进行存取,达到数据交互。例如:WebAssembly把视频的帧数据存在共享内存里,JavaScript则定时的获取内存里的帧数据。
为了方便程序员的使用,在SharedArrayBuffer和ArrayBuffer之上,提供了一些特定类型的Array。比如Int8Array,Int32Array。这些都成为TypeArray。
2.使用
始终使用new进行实例化:
var sab = new SharedArrayBuffer(1024); // 1024Byte的大小的共享内存
下面的列子,是main.js和worker.js的多线程间的共享数据通信。
main.js文件,是主程序文件,主进程。
var w = new Worker("worker-01.js")
w.postMessage("这是main.js发送的数据"); // 在main里发送信息到worker
w.onmessage = function (ev) { // main监听worker发过来的信息事件
console.log(ev.data);
}
worker-01.js文件,用于另起线程:
// worker的信息监听事件,获取main里postMessage发送过来的信息
onmessage = function (ev) {
console.log(ev.data);
postMessage("ho"); // 在worker里发送信息给main的onmessage
}
上面的代码在每次的postMessage和onmessage时,都需要进行数据的序列化和反序列化。这会消耗较多的性能。接着我们使用SharedArrayBuffer来优化上面的代码逻辑:
main.js
/* 使用属性crossOriginIsolated检查跨域隔离是否生效
生效,则可以使用SharedArrayBuffer */
if (crossOriginIsolated) {
var sab = new SharedArrayBuffer(1024);
var ia = new Int32Array(sab);
for(var i in ia){
ia[i] = i;
}
w.postMessage(ia);
} else {
w.postMessage("这是main.js发送的数据");
}
worker-01.js
var ia;
onmessage = function (ev) {
ia = ev.data; // ia直接就是Int32Array
console.log(ia[37]); // 37
}
3.安全
自2018年5月1日起,所有的主流浏览器都禁止了SharedArrayBuffer。而2020年后需要使用SharedArrayBuffer的话,可以进行一些安全设置,需要在服务端进行COOP设置,创建隔离环境:
Cross-Origin-Opener-Policy: same-origin # COOP 跨源开放者政策
Cross-Origin-Embedder-Policy: require-corp # COEP 跨源嵌入程序策略
window.opener
- 在COOP设置成’same-origin’时,window.open(url,‘_blank’),url和原页面是同域的,才可以在新页使用window.opener操作原页面。
- 当COOP设置成’unsafe-none’时,window.open(url,‘_blank’),新页可以直接使用window.opener操作原页面。
- 所以在场景:网站需要使用SharedArrayBuffer,又需要使用新页面通过https获取websocket的证书时,就可以整体的COOP设置为“same-origin”。单独的一个cert.html页面的COOP设置为“unsafe-none”。例如下面的nginx配置:
server{
location / {
root /usr/local/nignx/html;
index index.html index.htm;
}
location /cert.html {
root /usr/local/nignx/html;
add_header Cross-Origin-Opener-Policy 'unsafe-none';
}
add_header Cross-Origin-Opener-Policy 'same-origin';
add_header Cross-Origin-Embedder-Policy 'require-corp';
}