一般使用上,對於Module,我們只要知道他的url,然後可以取得救可以。而Instance,只要可以傳importObjects給他,然後取得Instance就可以,所以我們可以包裝一下:
(function(global) {
let module = null;
let url = null;
global.Wasm = Wasm;
function Wasm(_url) {
url = _url;
this.getModule = getModule;
this.getInstance = getInstance;
function getModule() {
if(module === null) {
return new Promise((resolve, reject) => {
WebAssembly.compileStreaming(fetch(url))
.then(_module => {
module = _module;
resolve(_module)
})
.catch(reason => reject(reason))
});
} else {
return new Promise((resolve, reject) => resolve(module));
}
};
function getInstance(importObjects) {
if(module === null) {
return new Promise((resolve, reject) => {
getModule()
.then(_module => {
if(!!importObjects) resolve(new WebAssembly.Instance(_module, importObjects));
else resolve(new WebAssembly.Instance(_module));
})
.catch(reason => reject(reason))
});
} else {
return new Promise((resolve, reject) => {
if(!!importObjects) resolve(new WebAssembly.Instance(module, importObjects));
else resolve(new WebAssembly.Instance(module));
});
}
}
}
})(window);
Javascript程式裡,是使用WebAssembly.compileStreaming()
搭配Fetch API回傳的Response物件來編譯並Cache編譯好的Module。然後在呼叫getModule()
時,會回傳可以取得Module的Promise。getInstance()
也差不多,只是多傳給他importObjects參數。
然後就可以像這樣使用:
<html>
<body>
<div id="panel"></div>
<script src="../wasm_util.js"></script>
<script>
let m = new Wasm('test001.wasm');
m.getInstance()
.then(instance => document.getElementById('panel').innerHTML = instance.exports.getfour())
</script>
</body>
</html>
為了展示,所以只是寫了一個固定會傳回4
的函數輸出:
(module
(func (export "getfour") (result i32)
i32.const 4))
執行後就在畫面出現4
:
要使用importObjects輸入函數給WebAssembly使用,只要定義好importObjects物件然後在呼叫getInstance()時傳給他就可以。
例如以下的WebAssembly程式:
(module
(func $alert (import "imports" "alert") (param i32))
(func $getfour (result i32)
i32.const 4
)
(func (export "exportFunc")
call $getfour
call $alert
)
)
在輸出的exportFunc
中,呼叫取得常數4
的函數,然後把他傳給輸入的函數。(再次簡單說明,WebAssembly程式是一個Stack Machine,所以在call $getfour
時會把結果放進堆疊,然後在call $alert
時會從堆疊取出傳給他)
網頁中:
<html>
<body>
<script src='../wasm_util.js'></script>
<script>
let importObjects = {
imports: {
alert: alert
}
};
let m = new Wasm('test002.wasm');
m.getInstance(importObjects)
.then(instance => instance.exports.exportFunc());
</script>
</body>
</html>
先定義好importObjects,結構要跟在WebAssembly中輸入的一致。在本例中是把alert
函數傳進去,然後我們呼叫輸出的exportFunc()
時,他就會呼叫alert顯示結果。
簡單地練習了一下,明天來看怎麼使用Memory。
幾篇看下來
發現自己要學習新的語言
已經沒有當年那種衝勁了
還好我是路人啦啦隊
不是參賽選手
題外話
話說今天在 LINE 裡只要寫到關鍵字
都會有動畫效果(不知道去年有嗎?)
Merry Christmas
聖誕快樂
其實我只是寫起來自嗨,實務上不會用這麼麻煩的方式寫程式XD
寫程式也能自嗨
費大真是天生吃這行飯的