Blazor项目中JavaScript函数返回Double值至C#时获取null的问题求助
Blazor项目中JavaScript函数返回Double值至C#时获取null的问题求助
我帮你分析下这个问题,核心原因是你JavaScript里的图片加载是异步操作,但原函数没正确处理异步返回,导致DetectSpeed在图片加载完成前就结束了,返回了undefined,所以Blazor那边拿到的是null,反序列化时就抛出了ArgumentNullException。
下面是具体的修复方案:
第一步:修改JavaScript函数,用Promise包裹异步逻辑
因为图片的onload是回调触发的异步操作,我们需要用Promise来封装这个过程,确保函数能等待图片加载完成后再返回计算好的速度值:
window.DetectSpeed = async () => { return new Promise((resolve) => { const userImageLink = "https://mobilesyrup.com/wp-content/uploads/2021/04/starlink-header-how-to-2048x1151.jpg"; let time_start, end_time; const downloadSize = 898080; const downloadImgSrc = new Image(); downloadImgSrc.onload = function () { end_time = new Date().getTime(); // 计算速度的逻辑保持不变 const timeDuration = (end_time - time_start) / 1000; const loadedBits = downloadSize * 8; const bps = (loadedBits / timeDuration).toFixed(2); const speedInKbps = (bps / 1024).toFixed(2); const speedInMbps = ((speedInKbps / 1024).toFixed(2)) / 100; console.log(speedInMbps); resolve(speedInMbps); // 将计算结果通过Promise返回 }; time_start = new Date().getTime(); downloadImgSrc.src = userImageLink; console.log("time start: " + time_start); }); };
第二步:简化C# Blazor代码,直接获取Double值
Blazor的IJSRuntime可以自动处理JavaScript基本类型(比如number)到C#类型的转换,不需要手动序列化/反序列化,所以我们可以直接调用InvokeAsync<double>:
protected bool IsVisible { get; set; } public List<string> VideoTags = new List<string>(); public void ToggleMenu() => IsVisible = !IsVisible; protected override async Task OnAfterRenderAsync(bool firstRender) { if(firstRender) { VideoTags = await videos.GetVideoTagsAsync(); await service.UpdateCurrentUserAsync(); // 直接获取Double类型结果,无需手动处理JSON double numm = await JsRuntime.InvokeAsync<double>("DetectSpeed"); Console.WriteLine("Bytearrax: " + numm.ToString()); Console.WriteLine("OnAfterRenderAsync was ended in Index.razor"); } }
为什么原来的代码会报错?
原JavaScript函数DetectSpeed里,displaySpeed是在图片加载完成后才执行的回调函数,但DetectSpeed本身在设置完图片src后就直接结束了,没有任何返回值(相当于返回undefined)。Blazor的IJSRuntime会把undefined转换为C#的null,所以你后续用JsonConvert.DeserializeObject<double>(json)时,就会因为传入了null而抛出参数为空的异常。
用Promise包裹后,函数会等待图片加载完成,把计算好的速度值通过resolve传递给Blazor,这样就能正确拿到有效的数值了。
备注:内容来源于stack exchange,提问作者libertarian1917
相关产品推荐
相关产品推荐

