请求重写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
相关产品推荐
相关产品推荐

