CefSharp Javascript 异步响应太快

CefSharp Javascript async response too fast

我的方法是访问每个 link,如果所有访问都从中接收 return 值。 问题是,当我启动代码时,我立即得到一个响应,显然是空的,因为并不是所有的 link 都被访问了。

    private async void ibtn_start_visiting_Click(object sender, EventArgs e)
    {
        string js = "var ele = document.querySelectorAll('#profiles * .tile__link');document.getElementsByClassName('js-scrollable')[0].scrollBy(0,30);ele.forEach(function(value,index){setTimeout(function(){if(index < ele.length-1){ele[index].click();}else{document.querySelectorAll('.search-results__item').forEach(e => e.parentNode.removeChild(e));document.getElementsByClassName('js-close-spotlight')[0].click();return 'hallo';}},1000 * index)})";
    
        await browser.EvaluateScriptAsync(js).ContinueWith(x =>
        {
            var response = x.Result;

            if (response.Success)
            {
                this.Invoke((MethodInvoker)delegate
                {
                    var res = (string)response.Result;
                    Console.WriteLine("Response: " + res);
                    
                    
                });
            }
            else {
                Console.WriteLine("NO");
            }
            
        });



    }

这是javascript:

var ele = document.querySelectorAll('#profiles * .tile__link');
document.getElementsByClassName('js-scrollable')[0].scrollBy(0,30);
ele.forEach(function(value,index){
    setTimeout(function(){
        if(index < ele.length-1){
            ele[index].click();
            
        }
        else{
            
            document.querySelectorAll('.search-results__item').forEach(e => e.parentNode.removeChild(e));
            document.getElementsByClassName('js-close-spotlight')[0].click();
            alert('hallo');
        }
    },1500 * index)
})

哦,我明白了。您的 javascript 正在使用 setTimeout,这相当于使您传递给它的函数也是异步的。 CefSharp 不知道那些 setTimeout 任务何时完成,因此早期 return。挂起的 javascript 代码最终会执行。要知道什么时候完成,您有几个选择:

  1. 通过完全摆脱 setTimeout 让您的异步 javascript 代码同步。
  2. 在您的异步 javascript 代码中设置一些全局变量,并在 C# 中定期检查您的网页以查看是否设置了该变量。
  3. 注册一些 JS 处理程序并在异步 javascript 完成时调用它。

#3 是我的最爱,因此您可以像这样在 C# 中注册该处理程序:

public class CallbackObjectForJs{
    public void showMessage(string msg){
        // we did it!
    }
}

webView.RegisterJsObject("callbackObj", new CallbackObjectForJs());

你的 JS 可能看起来像:

var totalTasks = 0;
function beginTask() {
  totalTasks++;
}
function completeTask() {
  totalTasks--;
  if (totalTasks === 0) {
    callbackObj("we finished!"); // this function was registered via C#
  }
}

var ele = document.querySelectorAll('#profiles * .tile__link');
document.getElementsByClassName('js-scrollable')[0].scrollBy(0,30);
ele.forEach(function(value,index){
    beginTask();  // NEW
    setTimeout(function(){
        ... // work
        completeTask();
    }, 1500 * index);
})

要使此更清洁,您可能需要查看 Javascript 的 Promise.all()