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

调用可能返回null的JS函数时,如何获取IJSObjectReference?

问题解决:处理Blazor中JS函数返回null时的IJSObjectReference异常

问题场景

我有如下TypeScript模块:

export function getIndexedDb() : IDBFactory | null
{
    if (window.indexedDB)
        return window.indexedDB;
    else
        return null;
}

想要在C#中获取该函数返回结果的IJSObjectReference,尝试了以下代码:

await using var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "xxxx.js");
await using var result = await module.InvokeAsync<IJSObjectReference>("getIndexedDb");

当window.indexedDB存在时代码运行正常,但当getIndexedDb()返回null时会报错:

Uncaught (in promise) Error: Cannot create a JSObjectReference from the value 'null'.

而且C#中无法捕获该异常,方法会直接停止执行后续代码,这是bug吗?另外我觉得用包装类的方案不够简洁:

class Nullable<T>
{
    value: T | null;
    constructor(value: T | null)
    {
        this.value = value;
    }
    getValue() : T | null
    {
        return this.value;
    }
    isNull() : boolean
    {
        return this.value === null;
    }
}

export function getIndexedDb() : Nullable<IDBFactory>
{
    if (window.indexedDB)
        return new Nullable<IDBFactory>(window.indexedDB);
    else
        return new Nullable<IDBFactory>(null);
}

解决方法

方法1:拆分判断与获取逻辑

在TS中新增判断函数,先确认IndexedDB是否存在,再安全获取实例:

// TS代码
export function hasIndexedDb(): boolean {
    return !!window.indexedDB;
}

export function getIndexedDb(): IDBFactory {
    return window.indexedDB!;
}

C#中先判断状态,再获取引用:

await using var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "xxxx.js");
var hasDb = await module.InvokeAsync<bool>("hasIndexedDb");

if (hasDb)
{
    await using var dbInstance = await module.InvokeAsync<IJSObjectReference>("getIndexedDb");
    // 在这里使用dbInstance操作IndexedDB
}

方法2:返回包含状态的普通对象

修改TS函数返回包含存在状态和实例的普通对象,无需额外包装类:

// TS代码
export function getIndexedDb(): { exists: boolean, instance?: IDBFactory } {
    if (window.indexedDB) {
        return { exists: true, instance: window.indexedDB };
    } else {
        return { exists: false };
    }
}

C#中定义对应实体类并处理:

// 定义C#实体类
public class IndexedDbResponse
{
    public bool Exists { get; set; }
}

// 调用代码
await using var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "xxxx.js");
var response = await module.InvokeAsync<IndexedDbResponse>("getIndexedDb");

if (response.Exists)
{
    var dbInstance = await module.InvokeAsync<IJSObjectReference>("getIndexedDb");
    // 使用实例
}

方法3:通过object类型中转避免异常

在C#中先以object类型接收返回值,再判断是否为IJSObjectReference:

await using var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "xxxx.js");
var resultObj = await module.InvokeAsync<object>("getIndexedDb");

if (resultObj is IJSObjectReference dbInstance)
{
    // 使用dbInstance
}
else
{
    // 处理null情况,比如提示不支持IndexedDB
}

关于异常无法捕获的问题

这不是bug,因为JS端抛出的Promise异常发生在JS线程,Blazor的.NET代码无法直接捕获未处理的JS Promise异常。要避免这种情况,要么在JS层确保不会抛出异常(比如上述方案),要么在JS中用try-catch包裹逻辑并返回错误状态,而不是抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:30:40