Я интегрировал некоторый код WASM (скомпилированный из кода Go) в Angular, чтобы использовать некоторые функции. На данный момент это делается только в одном месте и поэтому не используется во всем приложении. Я просто использовал «стандартную» процедуру для WASM и Go:
let go = new Go();
WebAssembly.instantiateStreaming(fetch('mywasm.wasm'), go.importObject).then((res) => {
go.run(res.instance);
myCoolWasmFunction();
});
Однако я хотел бы выполнить WASM в нескольких частях приложения и, таким образом, попытался перенести это в службу. Я смог использовать тему RxJS и прослушивать «запросы на выполнение» в этой функции после go.run(...), но я не мог ничего вернуть в другие части приложения.
По сути, я ищу чистый и удобный способ выполнения различных функций, предоставляемых wasm в приложении Angular. Должен ли я просто поместить материал wasm в index.html и создать сервис, который просто вызывает эти «глобально доступные» функции? Как я могу позволить angular распознавать их только с помощью файла .d.ts?
Я решил это с помощью этого Github Repo. Это так же просто, как создать общедоступную переменную внутри службы и при загрузке WASM установить экспортированные функции WASM в эту переменную, чтобы их можно было вызывать извне службы. Для следующего примера я добавил небольшой интерфейс машинописного текста, чтобы он работал с безопасностью типов:
Итак, в сервисе WASM могло бы выглядеть так:
private Suite: WasmSuite; // Here the exported functions are stored after wasm was initiated
/*
WasmSuite is defined like this:
type MyFunctionInterface = (input: string) => string;
interface WasmSuite {
myFunction: MyFunctionInterface;
}
*/
// This is just to let components know when WASM is ready
public ready: BehaviorSubject<boolean> = new BehaviorSubject(false);
constructor() {
// Init wasm, then update the ready state
this.init().then(_ => {
this.ready.next(true);
});
}
private async init() {
let go = new Go();
return WebAssembly.instantiateStreaming(
fetch('assets/main.wasm'),
go.importObject
).then((res) => {
go.run(res.instance);
// Set the Suite to an object containing the functions. The casting of the function is somewhat optional, but I think it's good practice.
this.Suite = {
myFunction: my_exported_func as MyFunctionInterface,
// "my_exported_func" is what I exported in Go via js.Global().Set("my_exported_func", js.FuncOf(myGoFunc))
};
});
}
public callMyFunction(input: string) {
// I like to publish methods to components instead of the suite object, so this is just an "interface" between callers and WASM.
return this.Suite.myFunction(input);
}
Как вы импортировали модули wasm? Я ненавижу, когда люди просто вставляют код, но забывают об импорте.... :-(
Извините, что вернулся после ГОД этой публикации, но у меня возникли проблемы с тем, как импортировать файл wasm, который я только что скомпилировал, и использовать его.
Импорт есть в коде: return WebAssembly.instantiateStreaming(fetch('assets/main.wasm'), go.importObject). Прочтите эту статью, чтобы узнать больше: golangbot.com/webassembly-using-go
Я не уверен на 100%, так как я не очень часто использовал Go-WASM (хотя я использовал GopherJS)... но я не думаю, что это будет работать так, как вы ожидаете. Я думаю, вам нужна единая точка входа в ваше приложение Go. В противном случае вы получите несколько запущенных экземпляров среды выполнения Go.