在Blazor应用中,由于前端渲染和运行逻辑基于.NET运行时,很多时候需要调用JavaScript的原生能力,比如操作DOM、调用浏览器API等。当JS函数执行完成后,Blazor侧往往需要知道执行结果或者执行完成的信号,才能继续推进后续的业务流程。

基础实现方式:使用IJSRuntime调用返回值的JS函数
Blazor提供了IJSRuntime接口用于和JavaScript进行互操作,大部分JS函数如果本身有返回值,我们可以直接通过调用方法获取返回值,这本身就是一种JS完成通知的体现。
JS侧定义有返回值的函数
首先在wwwroot目录下的index.html(Blazor WebAssembly)或者_Host.cshtml(Blazor Server)中添加JS函数:
// 定义一个简单的JS函数,执行完成后返回结果
function calculateSum(a, b) {
// 模拟耗时操作
const result = a + b;
return result;
}
Blazor侧调用并获取结果
在Blazor组件中注入IJSRuntime,然后调用JS函数获取返回值:
@inject IJSRuntime JSRuntime
<button @onclick="CallJsAndGetResult">调用JS获取结果</button>
<p>计算结果:@result</p>
@code {
private int result;
private async Task CallJsAndGetResult()
{
// 调用JS函数,获取返回值,JS函数执行完成才会返回
result = await JSRuntime.InvokeAsync<int>("calculateSum", 10, 20);
}
}
这种方式适用于JS函数执行逻辑简单,执行完成后直接返回结果的场景,当InvokeAsync方法返回时,就代表JS函数已经执行完成。
处理异步JS函数:基于Promise的通知获取
如果JS函数内部有异步操作,比如定时器、接口请求等,函数本身会返回Promise,这时候Blazor侧同样可以通过InvokeAsync获取Promise的结果,实现JS完成通知。
JS侧定义返回Promise的函数
// 模拟异步操作的JS函数,返回Promise
function asyncJsOperation() {
return new Promise((resolve) => {
setTimeout(() => {
const data = "异步操作完成的结果";
resolve(data);
}, 2000);
});
}
Blazor侧等待异步JS完成
@inject IJSRuntime JSRuntime
<button @onclick="CallAsyncJs">调用异步JS</button>
<p>异步结果:@asyncResult</p>
@code {
private string asyncResult;
private async Task CallAsyncJs()
{
// 等待JS的Promise完成,获取resolve的结果
asyncResult = await JSRuntime.InvokeAsync<string>("asyncJsOperation");
}
}
当JS的Promise执行resolve之后,Blazor侧的InvokeAsync才会返回对应的值,这样就实现了异步JS完成后的通知。
复杂场景:JS主动通知Blazor侧
有时候JS函数的执行不是由Blazor直接触发的,比如JS侧监听了某个浏览器事件,执行完成后需要主动通知Blazor侧,这时候可以使用DotNetObjectReference实现反向调用。
Blazor侧定义可被JS调用的方法
首先在Blazor组件中定义一个公共方法,并且用[JSInvokable]特性标记:
@inject IJSRuntime JSRuntime
<button @onclick="RegisterJsCallback">注册JS回调</button>
<p>JS通知内容:@notifyMsg</p>
@code {
private string notifyMsg;
// 可被JS调用的方法,需要标记JSInvokable特性
[JSInvokable]
public void OnJsCompleted(string msg)
{
notifyMsg = msg;
// 如果是在异步线程触发,需要调用StateHasChanged刷新UI
StateHasChanged();
}
private async Task RegisterJsCallback()
{
// 创建当前实例的引用,传递给JS
var dotNetRef = DotNetObjectReference.Create(this);
await JSRuntime.InvokeVoidAsync("registerJsCallback", dotNetRef);
}
}
JS侧保存引用并主动调用
在JS中接收Blazor传递过来的引用,在需要通知的时候调用对应的方法:
let dotNetRef = null;
// 保存Blazor传递过来的引用
function registerJsCallback(ref) {
dotNetRef = ref;
}
// JS执行完成后主动通知Blazor
function jsCompleteTask() {
if (dotNetRef) {
// 调用Blazor侧标记了JSInvokable的方法
dotNetRef.invokeMethodAsync("OnJsCompleted", "JS任务执行完成");
// 如果不需要再使用引用,需要释放避免内存泄漏
dotNetRef.dispose();
}
}
这种方式适合JS侧主动触发通知的场景,比如JS监听了按钮点击、WebSocket消息等,执行完成后直接调用Blazor侧的方法传递通知。
注意事项
- 使用
DotNetObjectReference之后,如果不再需要使用,一定要调用dispose方法释放,避免造成内存泄漏。 - Blazor Server模式下,JS互操作是通过SignalR连接实现的,需要注意网络延迟对通知时效性的影响。
InvokeAsync方法是异步的,调用的时候需要搭配await使用,避免逻辑执行顺序错误。- 如果JS函数执行出错,
InvokeAsync会抛出异常,建议在调用的时候添加try-catch处理异常场景。
总结
Blazor中获取JS完成通知的核心是基于IJSRuntime的互操作能力,根据JS函数的执行特性选择不同的实现方式。同步有返回值的JS函数可以直接通过InvokeAsync获取返回值;异步返回Promise的JS函数同样可以通过InvokeAsync等待结果;如果是JS侧主动通知的场景,则可以使用DotNetObjectReference配合[JSInvokable]特性实现反向调用。合理选择对应的方式,就能顺畅实现Blazor和JS之间的完成通知通信。
BlazorJS互操作JavaScriptdotnet_js_interop修改时间:2026-06-25 17:03:49