Pking
Pking

Reputation: 963

Combining observables

I have two observables: LoadLocal and LoadServer. LoadLocal loads and returns an element from a local source and LoadServer fetches it from a server. I want to combine them into another observable: Load. I want Load to get the element from LoadLocal, and if it is null, I want to return the element from LoadServer. Any ideas on how to do this?

Thanks


Details on the real scenario:

// loadLocal(id) gives me an observable that returns an asset from a local source
Func<Guid, IObservable<IAsset>> loadLocal = Observable.ToAsync<Guid, IAsset>(id => GetLocalAsset(id));

var svcClient = new ServiceClient<IDataService>();
var svc = Observable.FromAsyncPattern<Request, Response>(svcClient.BeginInvoke, svcClient.EndInvoke);

// calling loadServer(id) gives me an observable that returns an asset from a server
var loadServer = id => from response in svc(new Request(id)) select response.Asset;

// so at this point i can call loadServer(id).Subscribe() to get an asset with specified id from the server, or I can call loadLocal(id).Subscribe() to get it from local source.
// however I want another observable that combines the two so I can do: load(id).Subscribe() that gets the asset from loadLocal(id) and if it is null it gets it from loadServer(id)
var load = ???

The following almost gives me the desired result, however both loadLocal(id) and loadServer(id) gets run. If loadLocal(id) returns an element, I don't want loadServer(id) to run.

var load = id => loadLocal(id).Zip(loadServer(id), (local, server) => local ?? server);

Upvotes: 3

Views: 346

Answers (2)

Ana Betts
Ana Betts

Reputation: 74702

How about this:

loadLocal(id)
    .Where(x => x != null)
    .Concat(Observable.Defer(() => loadServer(id)))
    .Take(1);

Upvotes: 2

Thomas Levesque
Thomas Levesque

Reputation: 292735

Something like that perhaps?

var load = LoadLocal.Zip(LoadServer, (local, server) => local ?? server);

Upvotes: 1

Related Questions