开发者

noob question - Watching result of 2 Async methods that return Action<T>

开发者 https://www.devze.com 2023-03-19 01:55 出处:网络
I have the following 2 Async methods that use Ac开发者_如何学编程tion callbacks public interface IGeoCoordinateService

I have the following 2 Async methods that use Ac开发者_如何学编程tion callbacks

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

public interface IGooglePlacesService
{
    void FindLocations(GeoCoordinate geoCoordinate, SearchFilter searchFilter, Action<PlaceSearchResponse> searchCallback);
}
  • I have to make sure I have a result from the GeoCoordinateService before I want to execute the GooglePlacesService.
  • I also want to execute the GooglePlacesService everytime the GeoCoordinate changes (and not null)

Simplest way to do this with Rx? (I extreme noob so please be gentle with the Rx lingo)


The simplest way to do this would be to first convert your interfaces to IObservables. To do that, I'm going to make some assumptions about your API:

  • IGeoCoordinateService may call the positionCallback several times once started.
  • If IGeoCoordinateService calls exceptionCallback, it is done and will not call positionCallback again. (This assumption is needed to match the IObservable contract.)
  • IGooglePlacesService only calls the searchCallback once. (This assumption is useful for the SelectMany I will do later.)

From there, you can then write these functions:

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 (() => {});
                                        })
           }
}

Now that you can convert the services to IObservables, you can chain them like so (hopefully you can come up with a better function name):

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;
}

Note that as per usual for IObservables, calling ChainServices does nothing, you must call Subscribe on the returned IObservable to actually make the async calls.

Some things that the API could use, if you have any control:

  • some way to cancel the call part way through (IObservable does this by returning IDisposable from subscribe)
  • some way to tell when the IGeoCoordinateService is done to be able to call OnCompleted on the observers (assuming it calls the positionCallback multiple times)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号