You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebAssembly项目中如何同步调用JS模块的JsInterop方法?

如何在Blazor WebAssembly中同步导入并调用JS模块?

原异步实现代码

之前使用异步IJSRuntime加载JS模块并调用函数的代码如下:

模块初始化

private readonly Lazy<Task<IJSObjectReference>> moduleTask;
public LocalJsInterop(IJSRuntime jsRuntime)
{
    moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
        "import", "./../_content/WebPlayerControls/localJsInterop.js").AsTask());
}

异步调用函数

public async ValueTask<string> GetWindowLocation()
{
    var module = await moduleTask.Value;
    string value = await module.InvokeAsync<string>("GetWindowLocation");
    return value;
}

遇到的问题

尝试改用IJSInProcessRuntime实现同步调用时,遇到以下问题:

  • 直接用jsRuntime.Invoke<IJSObjectReference>("import", ...)加载模块后,只能调用异步的InvokeAsync<>,无法使用同步Invoke<>
  • 尝试使用IJSInProcessObjectReference初始化模块时,执行InvokeVoid会卡住;改用InvokeVoidAsync则抛出“未找到函数”异常,代码如下:
private readonly Lazy<IJSInProcessObjectReference> moduleTask;
public LocalJsInterop(IJSInProcessRuntime jsRuntime)
{
    moduleTask = new(() => jsRuntime.Invoke<IJSInProcessObjectReference>(
        "import", "./../_content/WebPlayerControls/localJsInterop.js"));
    m_jsRuntime = jsRuntime;
}

public void ShowMessage()
{
    var module = moduleTask.Value;
    module.InvokeVoid("ShowMessage");
}

解决方案

ES模块的import本身是异步API,没有同步版本,因此必须先异步完成模块加载,再基于已加载的模块进行同步调用。具体实现步骤如下:

修正后的模块初始化

使用Lazy<Task<IJSInProcessObjectReference>>延迟异步加载模块,并将加载后的IJSObjectReference转换为IJSInProcessObjectReference:

private readonly Lazy<Task<IJSInProcessObjectReference>> _moduleTask;
private readonly IJSInProcessRuntime _jsRuntime;

public LocalJsInterop(IJSInProcessRuntime jsRuntime)
{
    _jsRuntime = jsRuntime;
    _moduleTask = new Lazy<Task<IJSInProcessObjectReference>>(async () =>
    {
        // 异步导入ES模块
        var jsObjectRef = await _jsRuntime.InvokeAsync<IJSObjectReference>(
            "import", "./../_content/WebPlayerControls/localJsInterop.js");
        // 转换为进程内对象引用,支持同步调用
        return jsObjectRef as IJSInProcessObjectReference;
    });
}

同步调用函数

通过GetAwaiter().GetResult()同步等待模块加载完成,之后使用同步方法调用JS函数:

public void ShowMessage()
{
    var module = _moduleTask.Value.GetAwaiter().GetResult();
    module.InvokeVoid("ShowMessage");
}

public string GetWindowLocation()
{
    var module = _moduleTask.Value.GetAwaiter().GetResult();
    return module.Invoke<string>("GetWindowLocation");
}

注意事项

  1. JS模块导出格式:确保localJsInterop.js中的函数正确导出,示例如下:
export function ShowMessage() {
    alert("同步调用JS模块函数");
}

export function GetWindowLocation() {
    return window.location.href;
}
  1. 路径正确性:确认模块路径./../_content/WebPlayerControls/localJsInterop.js指向正确的静态资源位置,Blazor WebAssembly中需确保资源已正确嵌入或发布。

内容的提问来源于stack exchange,提问作者Anarkhys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 13:54:38