標籤:lex which returns tostring 一點 func this target world
之前開發的一個產品在上線後總有奇怪的BUG,經過一番調試後發現在使用CEF控制項的
EvaluateScriptAsync
這個方法的時候,並不能保證成功.
經過一番查詢,發現官方文檔(https://github.com/cefsharp/CefSharp/wiki/General-Usage#devtools)有這麼一段
2. How do you call a JavaScript method that returns a result?
If you need to evaluate code which returns a value, use the Task<JavascriptResponse> EvaluateScriptAsync(string script, TimeSpan? timeout)
method. JavaScript code is executed asynchronously and as such uses the .Net Task
class to return a response, which contains error message, result and a success (bool
) flag.
// Get Document Heightvar task = frame.EvaluateScriptAsync("(function() { var body = document.body, html = document.documentElement; return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); })();", null);task.ContinueWith(t =>{ if (!t.IsFaulted) { var response = t.Result; EvaluateJavaScriptResult = response.Success ? (response.Result ?? "null") : response.Message; }}, TaskScheduler.FromCurrentSynchronizationContext());
For a more detailed example check out this Gist
Notes
- Scripts are executed at the frame level, and every page has at least one frame (
MainFrame
)
- Only trivial values can be returned (like int, bool, string etc) - not a complex (user-defined) type which you have defined yourself. This is because there is no (easy) way to expose a random JavaScript object to the .NET world, at least not today. However, one possible technique is to turn the JavaScript object you wish to return to your .NET code into a JSON string with the JavaScript
JSON.toStringify()
method and return that string to your .NET code. Then you can decode that string into a .NET object with something like JSON.NET. See this MSDN link for more information. (https://msdn.microsoft.com/en-us/library/ie/cc836459(v=vs.94).aspx)
可以用這種方式擷取到JS的傳回值:
1 task.ContinueWith(t =>2 {3 if (!t.IsFaulted)4 {5 var response = t.Result;6 EvaluateJavaScriptResult = response.Success ? (response.Result ?? "null") : response.Message;7 }8 }, TaskScheduler.FromCurrentSynchronizationContext());
於是利用這一點,做了個"流水ID"
每次調用的時候就+1,另一頭代碼執行完後,返回該ID,如果調用失敗(或者返回的ID無法識別),則重新發起,如果另一頭收到連續兩次一樣的ID,則不做處理(但還是要返回ID的.).
這樣個方法也能用來解決某些丟包問題.
cefsharp 關於C# 調用JavaScript的一個坑