正在阅读有关 Wasm 的 MDN 文档。他们多次使用 WASM 模块这个术语。他们的定义如下:
WebAssembly.Module 对象包含已由浏览器编译的无状态 WebAssembly 代码,可以与 Workers 高效共享,并多次实例化。要实例化模块,请调用 WebAssembly.instantiate() 的辅助重载。
我不太明白这句话的意思。Web 程序集模块只是一个 Wasm 文件还是其他文件?
是否可以main在 Javascript 中调用 Go WebAssembly 函数,而不是?
让我先展示一下我做了什么。我的 Go 函数定义如下:
package main
import "fmt"
func main() {
fmt.Println("it works!")
}
func add(a, b int) int {
return a + b
}
Run Code Online (Sandbox Code Playgroud)
我只能调用main函数:
const go = new Go();
const data = await fetch("http://localhost:3333/main.wasm");
const result = await WebAssembly.instantiateStreaming(data, go.importObject);
go.run(result.instance);
Run Code Online (Sandbox Code Playgroud)
它it works!按预期返回。
然而,每当我试图调用add函数,我收到TypeError: Cannot read property 'add' of undefined at Welcome.getWasm,因为这两个result.exports,result.instance.exports不包含我的功能。我也尝试将 Go 函数大写,但无济于事。
因此,我开始想知道什么是问题——甚至可以从 Javascript 中调用一个随机的 Go …
当使用Closures为 JavaScript 提供回调时,有什么更好的方法来避免释放它们?所述WASM-定义BindGen引导建议使用.forget,但承认其基本上泄漏内存。
通常我们会存储句柄以便稍后在适当的时候被删除,但现在我们希望它是一个全局处理程序,所以我们使用该
forget方法来删除它而不会使闭包无效。请注意,这是 Rust 中的内存泄漏,因此应该谨慎地进行!
它暗示将闭包存储到适合丢弃的时间。在alexcrichton对上一个问题的回答中,他提到...
[...] 如果它 [...] 只被调用一次,那么你可以使用
Rc/RefCell来删除Closure闭包本身的内部(使用一些内部可变性恶作剧)
但他没有提供这种方法的例子。
在封闭的文档也给出了参考关闭返回JavaScript的背景下,以让它处理时释放参考的例子。
如果我们
cb放在这里,它会在时间间隔过去时引发异常。相反,我们将句柄返回给 JS,以便 JS 可以决定何时取消间隔并释放闭包。
我还想象有一些方法可以#[wasm_bindgen]在公共函数上使用生命周期或宏等功能来避免这个问题,但我无法弄清楚如何做到这一点。
我的问题是,使用.forget从 Rust 传递回 JavaScript 的闭包有哪些替代方法,我能否请您查看每个正在使用的选项的简单示例?
是否有一个 WebAssembly API 允许 WebAssembly 代码在没有 JavaScript 的情况下与浏览器交互?例如,访问网络、DOM 和 OpenGL。特别是对于 OpenGL,我必须首先通过 JavaScript 进行每个函数调用,这很荒谬。与此相关的必然是巨大的性能损失。
如果没有,是否有此类 API 的计划?
我有一个延迟加载的程序集,其中包含需要使用内置依赖注入实现注册的服务。如何注册这些服务,以便可以通过正常的注入机制将它们作为依赖项注入到延迟加载的程序集包含的组件中。
在 Blazor 中,我确实想用条件设置输入元素的样式。这是我现在使用的代码,它可以工作,但后来我遇到了一个问题,因为这里使用了三个不同的输入元素。
@if (MyNumber > 100)
{ <input type="number" @bind=MyNumber @bind:event="oninput" /> }
else if (MyNumber < 1)
{ <input type="number" @bind=MyNumber @bind:event="oninput" style="color:red" /> }
else
{ <input type="number" @bind=MyNumber @bind:event="oninput" style="background:lightgreen" /> }
Run Code Online (Sandbox Code Playgroud)
是否有更好的可能性来设置带有条件的样式?
编辑: 感谢您的回答,肯定有几种可能的解决方案。我什至使用以下属性找到了另一个:
<input type="number" @bind=MyNumber @bind:event="oninput" @attributes="SetStyle(MyNumber)" />
@code{
public Dictionary<string, object> SetStyle(int myNumber)
{
var dict = new Dictionary<string, object>();
if (myNumber > 100) { }
else if (myNumber < 1) dict.Add("style", "color:red");
else dict.Add("style", "background:lightgreen");
return dict;
}
Run Code Online (Sandbox Code Playgroud) 我有一个名为 Hello 的 JavaScript 事件:
addEventListener('hello', function () {
alert("event listener");
})
Run Code Online (Sandbox Code Playgroud)
并且,在另一个 javascript 函数中,我引发了该事件:
let event = new Event("hello", { bubbles: true });
document.dispatchEvent(event);
Run Code Online (Sandbox Code Playgroud)
我现在想做的是让事件在 javascript 函数中触发。Blazor 应该侦听事件,而不是调用 Blazor 方法的 javascript。
希望任何人都可以帮助我。
问候我,
exnternref我制定了一个基准测试,通过将 DOM 对象作为s 传递给 Wasm 函数来衡量调用 DOM API 的速度。这是要测量的函数(用 Rust 编写并由 rustc 1.55.0 编译):
#[wasm_bindgen]
pub fn append_and_remove(elem: web_sys::Element) {
let doc = web_sys::window().unwrap().document().unwrap();
let child = &doc.create_element("br").unwrap();
elem.append_with_node_1(child).unwrap();
let _ = elem.remove_child(child).unwrap();
}
Run Code Online (Sandbox Code Playgroud)
(完整代码请参见https://github.com/igrep/wasm-reference-types-examples )
我比较了两个 Wasm 模块(及其 JS 包装器)和等效的 JavaScript 代码:一个(“带引用类型”版本)使用 进行预处理wasm-bindgen --reference-types,另一个(“无引用类型”版本)仅使用 进行预处理wasm-bindgen。
这是运行一百万次的结果:
| 浏览器 | 标签 | 时间(毫秒) |
|---|---|---|
| 火狐94.0.1 | 无参考类型 | 2167 |
| 带参考类型 | 2687 | |
| 仅 JavaScript | 第637章 | |
| 铬95.0.4638.69 | 无参考类型 | 3432 |
| 带参考类型 | 4129 | |
| 仅 JavaScript | 1039 | |
| 边缘95.0.1020.44 | 无参考类型 | 3416 |
| 带参考类型 | 3858 | |
| 仅 JavaScript | 第1187章 … |
Mono/WASM 运行时(由 Blazor WebAssembly 使用)的Task.Yield底层如何工作?
澄清一下,我相信我对.NET Framework 和 .NET Core 的工作原理有很好的了解。Task.YieldMono 实现看起来并没有太大不同,简而言之,它可以归结为:
static Task Yield()
{
var tcs = new TaskCompletionSource<bool>();
System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,这也适用于 Blazor WebAssembly(在线尝试):
<label>Tick Count: @tickCount</label><br>
@code
{
int tickCount = System.Environment.TickCount;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender) CountAsync();
}
static Task Yield()
{
var tcs = new TaskCompletionSource<bool>();
System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
return tcs.Task;
}
async void CountAsync()
{
for (var …Run Code Online (Sandbox Code Playgroud) 我希望能够在视频到达某些指定帧时稳健地停止视频,以便根据使用 Blender、Manim 制作的视频进行口头演示...
我知道这个问题,但问题是视频没有完全停在好帧处。有时它会继续前进一帧,当我强制它返回到初始帧时,我们会看到视频向后退,这很奇怪。更糟糕的是,如果下一帧完全不同(不同的背景......),这将非常明显。
为了说明我的问题,我在这里创建了一个演示项目(只需单击“下一步”即可看到当视频停止时,有时会倒退)。完整的代码在这里。
我正在使用的代码的重要部分是:
var video = VideoFrame({
id: 'video',
frameRate: 24,
callback: function(curr_frame) {
// Stops the video when arriving on a frames to stop at.
if (stopFrames.includes(curr_frame)) {
console.log("Automatic stop: found stop frame.");
pauseMyVideo();
// Ensure we are on the proper frame.
video.seekTo({frame: curr_frame});
}
}
});
Run Code Online (Sandbox Code Playgroud)
到目前为止,我通过在结束前停止一帧然后使用seekTo(不确定这听起来如何)来避免这个问题,如此处所示。但正如您所看到的,有时当进入下一帧时,它会有点“冻结”:我想这是在seekTo.
PS:如果你知道 JS 中一种可靠的方法来了解给定视频的帧数,我也很感兴趣。
关于在桌面上预先剪切视频的想法,可以使用......但我过去在这方面有过不好的经验,特别是更改视频有时会产生一些故障。此外,它的使用可能会更复杂,这意味着视频应该手动剪切很多时间,重新编码......
编辑是否有任何解决方案,例如基于WebAssembly(与旧浏览器更兼容)或Webcodec(更高效,但尚未广泛传播)?Webcodec 似乎允许非常令人惊奇的事情,但我不知道如何使用它们。我很想听到基于它们的解决方案,因为 Firefox 尚不处理 webcodec。请注意,如果在此过程中音频不会丢失,那就太好了。如果我还可以根据要求显示控件,那就太好了。
编辑:我不确定这里发生了什么( …
webassembly ×10
blazor ×4
javascript ×3
.net ×2
rust ×2
wasm-bindgen ×2
assembly ×1
async-await ×1
browser ×1
c# ×1
closures ×1
go ×1
html5-video ×1
interop ×1
low-level ×1
video ×1
webcodecs ×1