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

请求重写CefSharp v57异步JS回调代码至v103版本

CefSharp v103 异步JS回调升级方案(替代RegisterJsObject)

从CefSharp v57升级到v103时,RegisterJsObject已被官方标记为过时,需改用JavascriptObjectRepository实现.NET对象与JS的双向调用。以下是适配v103的完整代码及关键注意点:

一、兼容原事件逻辑的升级代码

1. 保持回调类结构

public class JavascriptCallback
{
    // 收到Ajax结果时触发的事件
    public event Action OnResult;
    // 存储JS返回的结果
    public object Result { get; private set; }

    // 供JS调用的方法,传递异步结果
    public void SetResult(object result)
    {
        Result = result;
        OnResult?.Invoke();
    }
}

2. 浏览器初始化与对象注册

private ChromiumWebBrowser _browser;
private readonly JavascriptCallback _javascriptCallback = new JavascriptCallback();

// 监听浏览器初始化完成事件,确保注册时机正确
_browser.IsBrowserInitializedChanged += (s, e) =>
{
    if (_browser.IsBrowserInitialized)
    {
        // 用JavascriptObjectRepository替代RegisterJsObject
        _browser.JavascriptObjectRepository.Register(
            nameof(JavascriptCallback),
            _javascriptCallback,
            new BindingOptions
            {
                CamelCaseJavascriptNames = false,
                // 显式开启全局暴露,确保JS能访问到该对象
                IsExposedToGlobal = true
            }
        );
    }
};

// 订阅结果回调事件
Action onResultCallback = null;
onResultCallback = () =>
{
    _javascriptCallback.OnResult -= onResultCallback;
    // 输出JS返回的"hello"
    Console.WriteLine(_javascriptCallback.Result.ToString());
};
_javascriptCallback.OnResult += onResultCallback;

// 注入Ajax监听脚本(需确保浏览器初始化完成后执行)
string script = @"
$(document).ajaxSuccess((event, xhr, settings) => 
{
    JavascriptCallback.SetResult('hello');
});
";

if (_browser.IsBrowserInitialized)
{
    await _browser.EvaluateScriptAsync(script);
}
else
{
    // 等待浏览器初始化完成再执行脚本
    await Task.Run(async () =>
    {
        while (!_browser.IsBrowserInitialized)
        {
            await Task.Delay(100);
        }
        await _browser.EvaluateScriptAsync(script);
    });
}

二、关键变更说明

  • API替换:彻底移除RegisterJsObject,改用JavascriptObjectRepository.Register,这是v57之后的官方推荐API。
  • 注册时机:必须在IsBrowserInitialized为true时注册对象,否则注册会失效,这是升级时最容易踩的坑。
  • 全局暴露设置:显式设置IsExposedToGlobal = true,确保.NET对象被挂载到全局window对象下,JS才能直接调用。
  • 脚本执行时机:注入JS脚本前需确认浏览器已初始化,否则会出现找不到JavascriptCallback对象的错误。

三、更优异步处理方案(TaskCompletionSource)

推荐使用TaskCompletionSource替代事件,简化异步流程,代码更简洁:

1. 异步回调类

public class AsyncJavascriptCallback
{
    private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();

    // 提供异步等待结果的Task
    public Task<object> WaitForResultAsync() => _tcs.Task;

    // 供JS调用的结果传递方法
    public void SetResult(object result)
    {
        _tcs.TrySetResult(result);
    }
}

2. 使用方式

private ChromiumWebBrowser _browser;
private readonly AsyncJavascriptCallback _asyncCallback = new AsyncJavascriptCallback();

_browser.IsBrowserInitializedChanged += async (s, e) =>
{
    if (_browser.IsBrowserInitialized)
    {
        _browser.JavascriptObjectRepository.Register(
            nameof(AsyncJavascriptCallback),
            _asyncCallback,
            new BindingOptions
            {
                CamelCaseJavascriptNames = false,
                IsExposedToGlobal = true
            }
        );

        // 注入Ajax监听脚本
        string script = @"
$(document).ajaxSuccess((event, xhr, settings) => 
{
    AsyncJavascriptCallback.SetResult('hello');
});
";
        await _browser.EvaluateScriptAsync(script);

        // 异步等待JS返回结果
        var result = await _asyncCallback.WaitForResultAsync();
        Console.WriteLine(result.ToString()); // 输出"hello"
    }
};

这个方案无需手动管理事件订阅,异步流程更清晰,符合.NET现代异步编程规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:03:23