2016年5月24日火曜日

WebWorkerをHTAで利用する

HTAでもマルチスレッドで処理できる。
WebWorkerを使ううえでの注意点(別スレッドからはDOMにアクセスできないなど)はブラウザで使用する場合と同じ。

「C:\app\WebWorker.hta」のようなローカルPathから起動された場合はtempフォルダ内に外部スクリプトを出力して、それがWorker用のスクリプトファイルとして利用される。

「\\PC名\共有フォルダ\WebWorker.hta」のようなPathから起動された場合はBlobが上記の代わり利用されます。

Blobは作成元のHTAファイルの文字コードに関係なく、(おそらく)UTF-16になるため、HTAファイルもUTF-16(メモ帳でいうところのUnicode・・・)で保存しておかないと、実行時に文字化けしてエラーが出ます。

ローカルPathから起動された場合はFileSystemObjectのCreateTextFileでスクリプトファイルを出力するので、そのファイルと作成元HTAの文字コードが一致していれば問題ないので何でも良いですが、Blobを使う状況になっても文字コードを変えなくても良いように、HTAファイルもUTF-16で保存してください。(下記サンプルソースではCreateTextFileの第3引数をtrueにしてスクリプトファイルもUTF-16で出力していますので、HTAファイルもUTF-16にしないとエラーになります)

<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<title>web worker</title>
<body>
UNCパス上では動く。<br>
ローカルでは動かない(new Workerのところでsecurity errorになる)<br>
<a href="http://outofmem.tumblr.com/post/95984469624/html5javascriptweb-workers%E3%81%A8%E6%88%A6%E3%81%86">同一生成元ポリシーに違反してしまう?</a><br>
<br>
try~catchでBrobのがエラーになる場合はtempファイル作成して読ますようにしたらローカルでも動いた。
<script type="text/jscript">
function getFunctionBody(fun){
return fun.toString().trim().match(/^function[\s\w]*\([\w\s,]*\)\s*{([\w\W]*?)}$/)[1]
}
function fun2Worker(fun){
var str=getFunctionBody(fun), blob=new Blob([str], {type:'text/javascript'}), url=URL.createObjectURL(blob), worker
try{worker = new Worker(url)}
catch(e){
// Workerに渡すアドレスは同一生成元ポリシーを守らなければいけない。
// 変数urlの中身は「brob:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX」のランダムな文字列
// 呼び出し元ファイルのアドレスがローカルのものなら、ローカルPathしか渡せない。
var fs=new ActiveXObject('Scripting.FileSystemObject'), path=fs.getSpecialFolder(2)+'/'+fs.getTempName()+'.js', ws=fs.CreateTextFile(path, true, true)
ws.Write(str)
ws.Close()
worker = new Worker(path)
}
return worker
}
function abc(t){return t+'1'}
worker = fun2Worker(function(){
// ワーカー側スコープ
onmessage = function(e){ postMessage(abc(e.data)) }
function abc(t){return t+'0'}
})
worker.onmessage = function(e){
confirm(abc(e.data))
}
worker.postMessage('aaa')
</script>
</body>
</html>
view raw WebWorker.hta hosted with ❤ by GitHub

0 件のコメント:

コメントを投稿