Blazor Hybrid调用IJSRuntime报错:无法在WebView上下文外执行JS
我尝试在Blazor Hybrid的Razor组件中通过IJSRuntime导入.js文件,编写了InitialDocumentHtmlService服务代码及test.js文件,该代码在Blazor WebAssembly中可正常运行,但在Blazor Hybrid中抛出异常,异常信息为“Cannot invoke JavaScript outside of a WebView context”。
服务代码:
public class InitialDocumentHtmlService : IInitialDocumentHtmlService { private readonly IJSRuntime runtime; public InitialDocumentHtmlService(IJSRuntime jsRuntime) { this.runtime = jsRuntime; } public async Task<string> GetColorAsync(CancellationToken token) { // 此处抛出异常 var helloword = await runtime.InvokeAsync<IJSObjectReference>("import", token, "./test.js"); await helloword.InvokeVoidAsync("helloWorld", token); } }
test.js代码:
export function helloWorld() { console.log("Hello"); alert("hello"); }
异常调用栈:
This exception was originally thrown at this call stack: Microsoft.AspNetCore.Components.WebView.Services.WebViewJSRuntime.BeginInvokeJS(long, string, string, Microsoft.JSInterop.JSCallResultType, long) in WebViewJSRuntime.cs Microsoft.JSInterop.JSRuntime.InvokeAsync<TValue>(long, string, System.Threading.CancellationToken, object[]) Microsoft.JSInterop.JSRuntime.InvokeAsync<TValue>(string, System.Threading.CancellationToken, object[]) Microsoft.JSInterop.JSRuntimeExtensions.InvokeAsync<TValue>(Microsoft.JSInterop.IJSRuntime, string, System.Threading.CancellationToken, object[]) Datanex.Frontend.App.Modules.Services.InitialDocumentHtmlService.GetColorAsync(System.Threading.CancellationToken) in InitialDocumentHtmlService.cs Datanex.Frontend.App.Modules.Services.InitialApp.InitAsync(System.Threading.CancellationToken) in InirialApp.cs Datanex.Frontend.App.Component.Pages.Login.OnInitializedAsync() in Login.razor
异常成因
WebView上下文未就绪
Blazor Hybrid的IJSRuntime完全依赖WebView控件的运行上下文,只有当WebView完成初始化并加载完Blazor宿主页面后,才能建立有效的JS互操作通道。从调用栈可见,代码是在Login组件的OnInitializedAsync生命周期中触发调用的,这个阶段WebView尚未完成初始化,导致IJSRuntime找不到可用的WebView上下文。Hybrid与WASM的JS运行环境差异
Blazor WebAssembly直接运行在浏览器JS引擎中,IJSRuntime可随时访问全局JS环境;但Blazor Hybrid是通过原生WebView嵌入的,JS代码运行在WebView的独立沙箱环境里,必须等WebView完全加载、Blazor的JS互操作通道建立完成后,才能执行import这类JS方法。服务调用时机错误
你的InitialDocumentHtmlService被提前调用,此时绑定到IJSRuntime的WebView实例还未就绪。Blazor Hybrid中,IJSRuntime的有效实例和WebView控件强绑定,只有进入组件的OnAfterRenderAsync阶段后,WebView上下文才完全就绪,此时执行JS调用才不会触发该异常。
内容的提问来源于stack exchange,提问作者madiyyarrrr

