我如何等待EvaluateJavascript的结果?

时间:2016-01-07 11:55:47

标签: javascript c# xamarin xamarin.android

我有一个Android的CustomWebViewRenderer包含一个使用EvaluateJavascript处理javascript的事件,我有一个Callback对象来捕获javascript的结果,但我需要将该结果发送回初始调用函数链。现在OnRunJavascript在OnRecieveValue运行之前完成,因此e.Result设置不正确。

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();
                }
            }

1 个答案:

答案 0 :(得分:1)

一种选择是使用带有async / await的TaskCompletionSource。我喜欢这个,因为它很简单(相对较少的代码),让我快速将同步代码变成看起来像异步代码的东西。

使用您的示例,我将添加一个TaskCompletionSource并创建一个可以在稍后的程序中使用的任务。

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
    }
}

注意OnRunJavascript中的TODO,我相信,这是你想要完成的。该任务可以传递到其他地方等待,然后访问JavascriptResult。

我希望有所帮助。