載入和執行 WebAssembly 程式碼
要在 JavaScript 中使用 WebAssembly,您首先需要在編譯/例項化之前將模組載入到記憶體中。本文提供了有關可用於獲取 WebAssembly 位元組碼的不同機制的參考,以及如何編譯/例項化然後執行它的參考。
有哪些選項?
WebAssembly 尚未與<script type='module'>或import語句整合,因此沒有路徑可以讓瀏覽器使用匯入為您獲取模組。
較舊的WebAssembly.compile/WebAssembly.instantiate方法要求您在獲取原始位元組後建立一個包含 WebAssembly 模組二進位制檔案的ArrayBuffer,然後編譯/例項化它。這類似於new Function(string),除了我們用位元組陣列緩衝區(WebAssembly 原始碼)替換字元字串(JavaScript 原始碼)。
較新的WebAssembly.compileStreaming/WebAssembly.instantiateStreaming方法效率更高——它們直接對來自網路的原始位元組流執行操作,無需ArrayBuffer步驟。
那麼我們如何將這些位元組放入陣列緩衝區並進行編譯呢?以下部分將進行說明。
使用 Fetch
Fetch是一個方便的現代 API,用於獲取網路資源。
獲取 Wasm 模組最快、最有效的方法是使用較新的WebAssembly.instantiateStreaming()方法,該方法可以將fetch()呼叫作為其第一個引數,並且將一步完成獲取、編譯和例項化模組的操作,在模組從伺服器流式傳輸時訪問原始位元組碼
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject).then(
(results) => {
// Do something with the results!
},
);
如果我們使用較舊的WebAssembly.instantiate()方法(它不適用於直接流),我們需要額外的一步將獲取的位元組碼轉換為ArrayBuffer,如下所示
fetch("module.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, importObject))
.then((results) => {
// Do something with the results!
});
關於 instantiate() 過載
WebAssembly.instantiate()函式有兩種過載形式——上面顯示的形式將要編譯的位元組碼作為引數,並返回一個 Promise,該 Promise 解析為一個包含編譯後的模組物件及其例項化例項的物件。該物件如下所示
{
module: Module, // The newly compiled WebAssembly.Module object,
instance: Instance, // A new WebAssembly.Instance of the module object
}
注意:通常我們只關心例項,但如果我們想要快取它、透過postMessage()與其他工作執行緒或視窗共享它,或者建立更多例項,則擁有模組很有用。
注意:第二種過載形式將WebAssembly.Module物件作為引數,並直接返回一個包含例項物件作為結果的 Promise。請參閱第二個過載示例。
執行您的 WebAssembly 程式碼
一旦您在 JavaScript 中獲得了 WebAssembly 例項,您就可以開始使用透過WebAssembly.Instance.exports屬性匯出的其功能。您的程式碼可能如下所示
WebAssembly.instantiateStreaming(fetch("myModule.wasm"), importObject).then(
(obj) => {
// Call an exported function:
obj.instance.exports.exported_func();
// or access the buffer contents of an exported memory:
const dv = new DataView(obj.instance.exports.memory.buffer);
// or access the elements of an exported table:
const table = obj.instance.exports.table;
console.log(table.get(0)());
},
);
注意:有關 WebAssembly 模組匯出工作原理的更多資訊,請閱讀使用 WebAssembly JavaScript API和瞭解 WebAssembly 文字格式。
使用 XMLHttpRequest
XMLHttpRequest比 Fetch 略舊,但仍然可以愉快地用於獲取型別化陣列。同樣,假設我們的模組稱為simple.wasm
- 建立一個新的
XMLHttpRequest()例項,並使用其open()方法開啟請求,將請求方法設定為GET,並宣告我們要獲取的檔案的路徑。 - 這部分的關鍵是使用
responseType屬性將響應型別設定為'arraybuffer'。 - 接下來,使用
XMLHttpRequest.send()傳送請求。 - 然後,我們使用
load事件處理程式在響應完成下載時呼叫一個函式——在這個函式中,我們從response屬性獲取陣列緩衝區,然後將其饋送到我們的WebAssembly.instantiate()方法中,就像我們使用 Fetch 時一樣。
最終程式碼如下所示
const request = new XMLHttpRequest();
request.open("GET", "simple.wasm");
request.responseType = "arraybuffer";
request.send();
request.onload = () => {
const bytes = request.response;
WebAssembly.instantiate(bytes, importObject).then((results) => {
results.instance.exports.exported_func();
});
};
注意:您可以在xhr-wasm.html中看到此示例。