JavaScript WebWorkerでCRC32計算 スレッドによる非同期計算処理の例
以前と投稿したCRC32計算をWebWorker(スレッド)で非同期にしたものです。計算中でもUI関連の処理が停止しないため、快適な操作を維持できます。
WebWorker
async-awaitの並列処理ではなく、マルチスレッド処理を行うAPIです。
詳しくは検索で
いきなりソースコード
export async function main(){
let crcWorker = await CRC32Worker.open();
let data = new ArrayBuffer(100*1024*1024);
//data : crcを計算するデータ、ファイルとか
// 待っている間、UIを止めない
// workerに送ったdataは無効(空)に
let ret = await crcWorker.crc32(data);
data = ret.data;// 使い終わったデータを受け取る
let crs32 = ret.crc32;
console.log(crs32.toString(16));
}
interface CRC32WorkerResult{
crc32 : number,
data : ArrayBuffer, // データ返還
}
class CRC32Worker{
private worker : Worker;
private constructor(worker : Worker){
this.worker = worker;
}
static async open(){
// JSファイル
//return new CRC32Worker(new Worker("crc-worker.js"));
// 埋め込みJSソースコード
let codeURL = URL.createObjectURL(new Blob([workerCode]));
return new CRC32Worker(new Worker(codeURL));
}
// copy=false なら dataは無効(空)に
async crc32(data : ArrayBuffer, copy : boolean = false){
return await new Promise<CRC32WorkerResult>( (rs,rj)=>{
this.worker.postMessage(data, copy? [] : [data]);
this.worker.onmessage = (ev)=>{
rs(ev.data);
}
this.worker.onerror = rj;
});
}
}
// 埋め込みJSソースコード
let workerCode = `
onmessage = (e) => {
let crc32 = new CRC32().crc32(new Uint8Array(e.data));
//transferを使わない場合、送信時に複製、遅くなる可能性
postMessage({ crc32, data: e.data }, [e.data]); //データ返還
//postMessage(crc);//データ返還なし
};
//---------------------------------------
// crc32
class CRC32 {
static table = [];
constructor() {
if (CRC32.table.length > 0) {
return;
}
CRC32.initTable();
}
static initTable() {
for (let i = 0; i < 256; ++i) {
let r = i;
for (let j = 0; j < 8; ++j) {
if ((r & 1) == 1) {
r = 0xedb88320 ^ (r >>> 1);
}
else {
r = r >>> 1;
}
}
CRC32.table[i] = r >>> 0;
}
}
crc32(data) {
let crc = 0xffffffff;
let tbl = CRC32.table;
for (let o of data) {
crc = (crc >>> 8) ^ tbl[(crc ^ o) & 0xff];
}
crc = crc ^ 0xffffffff;
return crc >>> 0;
}
}
CRC32.initTable();
`;
埋め込みソースコードのTSファイル
interface CRC32WorkerResult{
crc32 : number,
data : ArrayBuffer, // データ返還
}
// window.postMessageと誤認されエラーにならないように
declare function postMessage(ev : any, transfer : any) : any;
onmessage = (e) => {
let crc32 = new CRC32().crc32(new Uint8Array(e.data));
//transferを使わない場合、送信時に複製、遅くなる可能性
postMessage({crc32, data:e.data}, [e.data]);//データ返還
//postMessage(crc);//データ返還なし
};
//---------------------------------------
// crc32
class CRC32{
static table : number[] = [];
constructor(){
if(CRC32.table.length > 0){ return; }
CRC32.initTable();
}
static initTable(){
for(let i=0; i<256; ++i){
let r = i;
for(let j=0; j<8; ++j){
if( (r & 1) == 1 ) { r = 0xedb88320^(r>>>1); }
else { r = r >>> 1; }
}
CRC32.table[i] = r >>> 0;
}
}
crc32(data : Uint8Array){
let crc = 0xffffffff;
let tbl = CRC32.table;
for(let o of data){
crc = (crc >>> 8) ^ tbl[(crc ^ o)&0xff];
}
crc = crc^0xffffffff;
return crc >>> 0;
}
}
CRC32.initTable();
いいなと思ったら応援しよう!
![zerogram](https://assets.st-note.com/production/uploads/images/79406964/profile_52d439edf0ed5fbf453ca56d5f22a6d9.png?width=600&crop=1:1,smart)