简体   繁体   中英

How do I await the result of EvaluateJavascript?

I have a CustomWebViewRenderer for Android that contains an event to process javascript using EvaluateJavascript, and I have a Callback object to catch the result of the javascript, but I need to send that result back up the chain to the initial calling function. Right now OnRunJavascript completes before OnRecieveValue runs, so e.Result is not set properly.

public void OnRunJavascript(object sender, JavascriptEventArgs e)
{
    if (Control != null)
    {
            var jsr = new JavascriptResult();
            Control.EvaluateJavascript(string.Format("javascript: {0}", e.Script), jsr);
            e.Result = jsr.Result;
     }
}


            public class JavascriptResult : Java.Lang.Object, IValueCallback
            {
                public string Result;
                public void OnReceiveValue(Java.Lang.Object result)
                {
                    string json = ((Java.Lang.String)result).ToString();
                    Result = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(json);
                    Notify();
                }
            }

One option is to use a TaskCompletionSource with async/await. I like this because it's simple (relatively little code), and let's me quickly turn synchronous code into something that looks like async code.

Using your example, I will add in a TaskCompletionSource and create a Task which can be used with await later on in your program.

public void OnRunJavascript(object sender, JavascriptEventArgs e)
{
    if (Control != null)
    {
        var jsr = new JavascriptResult();
        Control.EvaluateJavascript(string.Format("javascript: {0}", e.Script), jsr);
        // TODO await jsr.CompletionTask
        e.Result = jsr.Result;
     }
}


public class JavascriptResult : Java.Lang.Object, IValueCallback
{
    public string Result;

    public Task CompletionTask {get { return jsCompletionSource.Task; } }

    private TaskCompletionSource<bool> jsCompletionSource = new TaskCompletionSource<bool>();

    public void OnReceiveValue(Java.Lang.Object result)
    {
        string json = ((Java.Lang.String)result).ToString();
        Result = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(json);
        Notify();
        jsCompletionSource.SetResult(true); // completes the Task
        // the await will finish
    }
}

Notice the TODO inside OnRunJavascript which, I believe, is what you're looking to accomplish. That Task can be passed somewhere else to be awaited and then access the JavascriptResult.

I hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM