• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • WebAssembly.instantiate()

    这是一个实验中的功能
    此功能某些浏览器尚在开发中,请参考浏览器兼容性表格以得到在不同浏览器中适合使用的前缀。由于该功能对应的标准文档可能被重新修订,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。

    WebAssembly.instantiate()是编译和实例化 WebAssembly 代码的主要方法.这个方法有两个重载方式:

    • 第一种重载使用WebAssembly二进制代码的 typed array 或 ArrayBuffer 形式进行编译和实例化.返回的Promise会携带已编译的WebAssembly.Instance.
    • 第二种重载使用已编译的WebAssembly.Module, 返回的Promise携带一个Module的实例化对象Instance.如果这个Module已经被编译了或者是从缓存中获取的(retrieved from cache),那么这种重载方式是非常有用的.

    语法

    主重载方式—使用wasm二进制代码

    Promise<ResultObject> WebAssembly.instantiate(bufferSource, importObject);
    

    参数

    bufferSource
    一个包含你想编译的wasm模块二进制代码的 typed array(类型数组)or ArrayBuffer(数组缓冲区)
    importObject可选
    一个将被导入到新创建实例中的对象,它包含的值有函数、WebAssembly.Memory对象等等。编译的模块中,对于每一个导入的值都要有一个与其匹配的属性与之相对应,否则将会抛出 WebAssembly.LinkError。

    返回值

    解析为包含两个字段的ResultObject的一个Promise:

    • module:一个被编译好的 postMessage()被分享,或者缓存到 IndexedDB。
    • instance:一个包含所有 Exported WebAssembly functions的WebAssembly.Instance对象。

    异常

    • 如果参数的类型或结构不正确,将会抛出异常TypeError.
    • 如果操作失败,promise 将会被 reject 掉,根据失败的原因不同,会抛出3种异常,WebAssembly.RuntimeError

    第二种重载—使用模块对象

    Promise<WebAssembly.Instance> WebAssembly.instantiate(module, importObject);
    

    参数

    module
    将被实例化的WebAssembly.Module对象。
    importObject可选
    一个将被导入到新创建实例中的对象,它包含的值有函数、WebAssembly.Memory对象等等。编译的模块中,对于每一个导入的值都要有一个与其匹配的属性与之相对应,否则将会抛出 WebAssembly.LinkError。

    返回值

    一个解析为WebAssembly.InstancePromise对象。

    异常

    • 如果参数的类型或结构不正确,将抛出异常TypeError
    • 如果操作失败,promise 将会被 reject 掉,根据失败的原因不同,会抛出3种异常,WebAssembly.RuntimeError

    例子

    第一种重载例子

    使用 fetch 获取一些 WebAssembly 二进制代码后,我们使用WebAssembly.instantiate()方法编译并实例化模块,在此过程中,导入了一个 Javascript 方法在 WebAssembly 模块中,接下来我们使用Instance导出的Exported WebAssembly 方法。

    var importObject = {
      imports: {
        imported_func: function(arg) {
          console.log(arg);
        }
      },
      env: {
        abort: () => {},
      },
    };
    
    /* 2019-08-03:importObject必须存在env对象以及env对象的abort方法 */
    
    fetch('simple.wasm').then(response =>
      response.arrayBuffer()
    ).then(bytes =>
      WebAssembly.instantiate(bytes, importObject)
    ).then(result =>
      result.instance.exports
    );
    

    注:查看GitHub(在线实例)的 index.html 中一个相似的例子,使用了我们的fetchAndInstantiate()库函数

    第二种重载例子

    下面的例子(查看我们GitHub的 index-compile.html 例子,可在线演示)使用compile()方法编译了 simple.wasm 字节码,然后通过 postMessage()发送给一个线程 worker。

    var worker = new Worker("wasm_worker.js");
    
    fetch('simple.wasm').then(response =>
      response.arrayBuffer()
    ).then(bytes =>
      WebAssembly.compile(bytes)
    ).then(mod =>
      worker.postMessage(mod)
    );
    

    在线程中(查看wasm_worker.js)我们定义了一个导入对象供模块使用,然后设置了一个事件处理函数来接收主线程发来的模块。当模块被接收到后,我们使用WebAssembly.instantiate()方法创建一个实例并且调用它从内部导出的函数。

    var importObject = {
      imports: {
        imported_func: function(arg) {
          console.log(arg);
        }
      }
    };
    
    onmessage = function(e) {
      console.log('module received from main thread');
      var mod = e.data;
    
      WebAssembly.instantiate(mod, importObject).then(function(instance) {
        instance.exports.exported_func();
      });
    };