我正在使用可与回调配合使用的网络API。所以基本上,我有一堆方法调用,我需要在这个第三方库中使用,如下所示:
void SendNetworkRequest(string requestType, Action<Response> callback)
我发现代码有点古怪,因为我依赖于来自第三方API的网络资源的所有方法也需要自己实现回调。例如,在我的主场景中,我可能想要获取玩家信息,我的代码看起来像这样:
void InitMainScene()
{
_networkHelper.SendNetworkRequest("GetPlayersInfo",OnPlayerInfoResponse);
}
void OnPlayerInfoResponse(Response response)
{
_playerInfo = response.Info;
}
我最近进入了RX并在我的代码中使用它。我读过一些关于async / await的内容。我已经尝试了很多,特别是对于RX,并尝试使用Observable.FromAsync()但无法使其工作..
我在这里缺少什么?如何编写更清晰且不需要使用RX或async / await进行回调的代码?以下是我正在寻找的伪代码:
void InitMainScene()
{
_playerInfo = Overservable.DoMagicThing<Response>( () => {
_networkHelper.SendNetworkRequest("GetPlayersInfo",(r) =>{return r;}); });
}
答案 0 :(得分:1)
我不确定RX。但是,您可以将基于回调的SendNetworkRequest转换为可以执行的任务,如下所示:
void SendNetworkRequest(string requestType, Action<Response> callback)
{
// This code by third party, this is here just for testing
if (callback != null)
{
var result = new Response();
callback(result);
}
}
Task<Response> SendNetworkRequestAsync(string requestType)
{
return Task.Run(() =>
{
var t = new TaskCompletionSource<Response>();
SendNetworkRequest(requestType, s => t.TrySetResult(s));
return t.Task;
});
}
现在您可以使用async / await更自然地使用SendNetworkRequestAsync
答案 1 :(得分:1)
以下是如何使用Rx完成的。我为Response
换了string
只是为了让我可以编译和测试,但是可以轻易地换回来。:
public IObservable<string> SendNetworkRequestObservable(string requestType)
{
return Observable.Create<string>(observer =>
{
SendNetworkRequest(requestType, s => observer.OnNext(s));
observer.OnCompleted();
return Disposable.Empty;
});
}
// Define other methods and classes here
public void SendNetworkRequest(string requestType, Action<string> callback)
{
callback(requestType); // implementation for testing purposes
}
答案 2 :(得分:1)
这是我对Rx这样做的看法。
在NetworkHelper
类中添加此方法:
public IObservable<Response> SendNetworkRequestObservable(string requestType)
{
return
Observable
.Create<Response>(observer =>
{
Action<Response> callback = null;
var callbackQuery =
Observable
.FromEvent<Response>(h => callback += h, h => callback -= h)
.Take(1);
var subscription = callbackQuery.Subscribe(observer);
this.SendNetworkRequest(requestType, callback);
return subscription;
});
}
这会创建一个observable,在内部使用Observable.FromEvent(...).Take(1)
创建一个observable,基于期望对传递给Action<Response> callback
方法的SendNetworkRequest
进行单次调用。
唯一的问题是调用发生在当前线程完成之前。如果您希望此代码在后台线程上运行,但将结果返回到当前线程,则可以执行以下操作:
public IObservable<Response> SendNetworkRequestObservable(string requestType)
{
return
Observable
.Start(() =>
Observable
.Create<Response>(observer =>
{
Action<Response> callback = null;
var callbackQuery =
Observable
.FromEvent<Response>(h => callback += h, h => callback -= h)
.Take(1);
var subscription = callbackQuery.Subscribe(observer);
this.SendNetworkRequest(requestType, callback);
return subscription;
}))
.Merge();
}
你可以这样称呼它:
var _playerInfo =
_networkHelper
.SendNetworkRequestObservable("GetPlayersInfo")
.Wait();
只是旁注:您的DoMagicThing
是同步通话。在Rx中进行.Wait()
通话,但最好只使用普通.Subscribe
。
根据评论,您可以使用async
:
async void InitMainScene()
{
_playerInfo = await _networkHelper.SendNetworkRequestObservable("GetPlayersInfo");
}