在 CefSharp 中从 JS 调用异步方法

Laj*_*jos 3 .net javascript c# cefsharp

如何从 CefSharp 中的 JS 调用 .NET 异步方法。我想调用一个等待控制台应用程序调用的方法。

我的想法如下:我用下面的签名调用一个方法:

public async Task<int> Calculate(){
Run Code Online (Sandbox Code Playgroud)

当它完成时,它的结果由 JS 端的承诺返回。目前,它不起作用。完成后没有回调,然后我无法再次调用它。

谢谢

Dre*_*kes 5

我遇到了同样的问题。

一个丑陋的解决方法似乎是将您的方法修改为async void并接受两个IJavascriptCallback参数(resolvereject)。

例如:

public class MyCalculator
{
    public async void CalcAsync(
        string name,
        IJavascriptCallback resolve,
        IJavascriptCallback reject)
    {
        try
        {
            if (resolve.IsDisposed)
                return;

            int i = /* compute i */;

            if (!resolve.IsDisposed)
               await resolve.ExecuteAsync(i);
        }
        catch (Exception e)
        {
            if (!reject.IsDisposed)
                await reject.ExecuteAsync(e.ToString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注册为:

browser.RegisterAsyncJsObject("myCalculator", new MyCalculator());
Run Code Online (Sandbox Code Playgroud)

然后在你的 JavaScript 中:

public class MyCalculator
{
    public async void CalcAsync(
        string name,
        IJavascriptCallback resolve,
        IJavascriptCallback reject)
    {
        try
        {
            if (resolve.IsDisposed)
                return;

            int i = /* compute i */;

            if (!resolve.IsDisposed)
               await resolve.ExecuteAsync(i);
        }
        catch (Exception e)
        {
            if (!reject.IsDisposed)
                await reject.ExecuteAsync(e.ToString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样拉出模式:

private static async Task Promisify(IJavascriptCallback resolve, IJavascriptCallback reject, Func<Task> action)
{
    try
    {
        if (!resolve.IsDisposed)
            await action();

        if (!resolve.IsDisposed)
            await resolve.ExecuteAsync();
    }
    catch (Exception e)
    {
        if (!reject.IsDisposed)
            await reject.ExecuteAsync(e.ToString());
    }
}

private static async Task Promisify<T>(IJavascriptCallback resolve, IJavascriptCallback reject, Func<Task<T>> action)
{
    try
    {
        var result = default(T);

        if (!resolve.IsDisposed)
            result = await action();

        if (!resolve.IsDisposed)
            await resolve.ExecuteAsync(result);
    }
    catch (Exception e)
    {
        if (!reject.IsDisposed)
            await reject.ExecuteAsync(e.ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

绑定对象的方法将类似于:

public class MyCalculator
{
    public async void CalcAsync(
        string name,
        IJavascriptCallback resolve,
        IJavascriptCallback reject)
    {
        Promisify(resolve, reject, () => /* compute i */);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想使用的(假设的)API 类似于:

public class MyCalculator
{
    public async Task<int> CalcAsync(string name) => /* compute i */;
}
Run Code Online (Sandbox Code Playgroud)

和:

browser.RegisterAsyncJsObject("myCalculator", new MyCalculator());
Run Code Online (Sandbox Code Playgroud)