DotNetBrowser 和 Promises
DotNetBrowser and Promises
我将 DotNetBrowser 用作 .Net 应用程序中的一种无头 Javascript 引擎。 DotNetBrowser 似乎不支持 Promises,或者我没有正确调用它们。
在 JS 中:
window.fooAsyncMethod = () => {
return new Promise((resolve, reject) => {
resolve('async value to resolve');
});
}
在 C# 中:
var result = await browser.MainFrame.ExecuteJavascript("await window.fooAsyncMethod()")
在这种情况下,结果始终为空。我也试过 async/await,总是收到 null:
window.fooAsyncMethod = async () => {
return await someOtherAsyncMethod()
}
DotNetBrowser 是否支持运行异步javascript?如果是这样,我如何实现等待异步操作的结果并在 C# 中解析该值?
查看 JS-.NET bridge examples it appears that it does support promises 但是它们使用起来有点复杂。
如果您像这样在 C# 端实现一种 promise 对象:
public static class JsObjectExtensions
{
#region Methods
public static JsPromise AsPromise(this IJsObject jsObject) => JsPromise.AsPromise(jsObject);
#endregion
}
public sealed class JsPromise
{
private readonly IJsObject jsObject;
#region Constructors
private JsPromise(IJsObject jsObject)
{
this.jsObject = jsObject;
}
#endregion
public static JsPromise AsPromise(IJsObject jsObject) => !IsPromise(jsObject) ? null : new JsPromise(jsObject);
public JsPromise Catch(Func<object, object> onRejected)
{
IJsObject newPromise = jsObject.Invoke("catch", onRejected) as IJsObject;
return new JsPromise(newPromise);
}
public Task<Result> ResolveAsync()
{
TaskCompletionSource<Result> promiseTcs = new TaskCompletionSource<Result>();
Then(obj => { promiseTcs.TrySetResult(Fulfilled(obj)); },
obj => { promiseTcs.TrySetResult(Rejected(obj)); });
promiseTcs.Task.ConfigureAwait(false);
return promiseTcs.Task;
}
public void Then(Action<object> onFulfilled, Action<object> onRejected = null)
{
jsObject.Invoke("then", onFulfilled, onRejected);
}
public JsPromise Then(Func<object, object> onFulfilled, Func<object, object> onRejected = null)
{
IJsObject newPromise = jsObject.Invoke("then", onFulfilled, onRejected) as IJsObject;
return new JsPromise(newPromise);
}
private Result Fulfilled(object o) => new Result(ResultState.Fulfilled, o);
private static bool IsPromise(IJsObject jsObject)
{
if (jsObject == null || jsObject.IsDisposed)
{
return false;
}
IJsObject promisePrototype = jsObject.Frame.ExecuteJavaScript<IJsObject>("Promise.prototype").Result;
return promisePrototype.Invoke<bool>("isPrototypeOf", jsObject);
}
private Result Rejected(object o) => new Result(ResultState.Rejected, o);
public enum ResultState
{
Fulfilled,
Rejected
}
public class Result
{
public object Data { get; }
public ResultState State { get; }
internal Result(ResultState state, object data)
{
State = state;
Data = data;
}
}
}
然后您将能够像这样调用 promise:
IJsObject window = browser.MainFrame.ExecuteJavaScript<IJsObject>("window").Result;
//Prepare promise handlers
Action<object> promiseResolvedHandler = o => Console.WriteLine("Success: " + o);
Action<object> promiseRejectedHandler = o => Console.Error.WriteLine("Error: " + o);
//Create a promise that is fulfilled
Console.WriteLine("Create a promise that is fulfilled...");
IJsObject promise1 = window.Invoke<IJsObject>("CreatePromise", true);
//Append fulfillment and rejection handlers to the promise
promise1.Invoke("then", promiseResolvedHandler, promiseRejectedHandler);
//Create a promise that is rejected
Console.WriteLine("Create a promise that is rejected...");
IJsObject promise2 = window.Invoke<IJsObject>("CreatePromise", false);
//Append fulfillment and rejection handlers to the promise
promise2.Invoke("then", promiseResolvedHandler, promiseRejectedHandler);
CreatePromiseAsync(window).Wait();
请注意,以上所有代码均直接取自他们的Promises Example。
我将 DotNetBrowser 用作 .Net 应用程序中的一种无头 Javascript 引擎。 DotNetBrowser 似乎不支持 Promises,或者我没有正确调用它们。
在 JS 中:
window.fooAsyncMethod = () => {
return new Promise((resolve, reject) => {
resolve('async value to resolve');
});
}
在 C# 中:
var result = await browser.MainFrame.ExecuteJavascript("await window.fooAsyncMethod()")
在这种情况下,结果始终为空。我也试过 async/await,总是收到 null:
window.fooAsyncMethod = async () => {
return await someOtherAsyncMethod()
}
DotNetBrowser 是否支持运行异步javascript?如果是这样,我如何实现等待异步操作的结果并在 C# 中解析该值?
查看 JS-.NET bridge examples it appears that it does support promises 但是它们使用起来有点复杂。
如果您像这样在 C# 端实现一种 promise 对象:
public static class JsObjectExtensions
{
#region Methods
public static JsPromise AsPromise(this IJsObject jsObject) => JsPromise.AsPromise(jsObject);
#endregion
}
public sealed class JsPromise
{
private readonly IJsObject jsObject;
#region Constructors
private JsPromise(IJsObject jsObject)
{
this.jsObject = jsObject;
}
#endregion
public static JsPromise AsPromise(IJsObject jsObject) => !IsPromise(jsObject) ? null : new JsPromise(jsObject);
public JsPromise Catch(Func<object, object> onRejected)
{
IJsObject newPromise = jsObject.Invoke("catch", onRejected) as IJsObject;
return new JsPromise(newPromise);
}
public Task<Result> ResolveAsync()
{
TaskCompletionSource<Result> promiseTcs = new TaskCompletionSource<Result>();
Then(obj => { promiseTcs.TrySetResult(Fulfilled(obj)); },
obj => { promiseTcs.TrySetResult(Rejected(obj)); });
promiseTcs.Task.ConfigureAwait(false);
return promiseTcs.Task;
}
public void Then(Action<object> onFulfilled, Action<object> onRejected = null)
{
jsObject.Invoke("then", onFulfilled, onRejected);
}
public JsPromise Then(Func<object, object> onFulfilled, Func<object, object> onRejected = null)
{
IJsObject newPromise = jsObject.Invoke("then", onFulfilled, onRejected) as IJsObject;
return new JsPromise(newPromise);
}
private Result Fulfilled(object o) => new Result(ResultState.Fulfilled, o);
private static bool IsPromise(IJsObject jsObject)
{
if (jsObject == null || jsObject.IsDisposed)
{
return false;
}
IJsObject promisePrototype = jsObject.Frame.ExecuteJavaScript<IJsObject>("Promise.prototype").Result;
return promisePrototype.Invoke<bool>("isPrototypeOf", jsObject);
}
private Result Rejected(object o) => new Result(ResultState.Rejected, o);
public enum ResultState
{
Fulfilled,
Rejected
}
public class Result
{
public object Data { get; }
public ResultState State { get; }
internal Result(ResultState state, object data)
{
State = state;
Data = data;
}
}
}
然后您将能够像这样调用 promise:
IJsObject window = browser.MainFrame.ExecuteJavaScript<IJsObject>("window").Result;
//Prepare promise handlers
Action<object> promiseResolvedHandler = o => Console.WriteLine("Success: " + o);
Action<object> promiseRejectedHandler = o => Console.Error.WriteLine("Error: " + o);
//Create a promise that is fulfilled
Console.WriteLine("Create a promise that is fulfilled...");
IJsObject promise1 = window.Invoke<IJsObject>("CreatePromise", true);
//Append fulfillment and rejection handlers to the promise
promise1.Invoke("then", promiseResolvedHandler, promiseRejectedHandler);
//Create a promise that is rejected
Console.WriteLine("Create a promise that is rejected...");
IJsObject promise2 = window.Invoke<IJsObject>("CreatePromise", false);
//Append fulfillment and rejection handlers to the promise
promise2.Invoke("then", promiseResolvedHandler, promiseRejectedHandler);
CreatePromiseAsync(window).Wait();
请注意,以上所有代码均直接取自他们的Promises Example。