noob question - 观察返回Action <t> </t>的2个Async方法的结果

时间:2011-07-08 13:47:54

标签: system.reactive

我有以下2个使用Action回调的异步方法

public interface IGeoCoordinateService
{
    void Start(Action<GeoPosition<GeoCoordinate>> positionCallback, Action<Exception> exceptionCallback);
}

public interface IGooglePlacesService
{
    void FindLocations(GeoCoordinate geoCoordinate, SearchFilter searchFilter, Action<PlaceSearchResponse> searchCallback);
}
  • 在我想要执行GooglePlacesService之前,我必须确保我有来自GeoCoordinateService的结果。
  • 我还希望每次GeoCoordinate更改时都执行GooglePlacesService(而不是null)

使用Rx执行此操作的最简单方法是什么? (我极端的菜鸟所以请温柔地使用Rx术语)

1 个答案:

答案 0 :(得分:2)

最简单的方法是首先将接口转换为IObservables。为此,我将对您的API做出一些假设:

  • 一旦启动,IGeoCoordinateService可能会多次调用positionCallback。
  • 如果IGeoCoordinateService调用exceptionCallback,它就完成了,不会再次调用positionCallback。 (需要这个假设来匹配IObservable合同。)
  • IGooglePlacesService只调用一次searchCallback。 (这个假设对我以后会做的SelectMany很有用。)

然后,您可以编写这些函数:

public IObservable<GeoPosition<GeoCoordinate>> ToObservable(this IGeoCoordinateService service)
{
    return Observable.Create((IObserver<GeoPosition<GeoCoordinate>> observer) =>
                             {
                                 service.Start(observer.OnNext, observer.OnError);
                                 //nothing to do on unsubscribe, cannot cancel run
                                 return (() => {});
                             })
}

public Func<GeoCoordinate, SearchFilter, IObservable<PlaceSearchResponse>>
ToObservable(IGooglePlacesService service)
{
    return (coord, filter) =>
           {
               return Observable.Create((IObserver<PlaceSearchResponse> observer) =>
                                        {
                                            service.FindLocations(coord, filter,
                                                                  (value) =>
                                                                  {
                                                                      observer.OnNext(value);
                                                                      observer.OnCompleted();
                                                                  });
                                            //nothing to do on unsubscribe, cannot cancel run
                                            return (() => {});
                                        })
           }
}

现在您可以将服务转换为IObservables,您可以将它们链接起来(希望您可以提供更好的函数名称):

public IObservable<PlaceSearchResponse> ChainServices(IGeoCoordinateService geo, IGooglePlacesService place, SearchFilter filter)
{
    return from pos in geo.ToObservable()
           where pos != null && pos.Coordinate != null
           from placeResponsen place.ToObservable()(pos.Coordinate, filter)
           select placeResponse;
}

请注意,按照IObservables的惯例,调用ChainServices什么都不做,你必须在返回的IObservable上调用Subscribe来实际进行异步调用。

如果您有任何控制权,API可以使用的一些内容:

  • 某种方式取消部分通过(IObservable通过从订阅返回IDisposable来实现)
  • 告诉IGeoCoordinateService何时完成能够在观察者上调用OnCompleted的某种方式(假设它多次调用positionCallback)