简体   繁体   English

使用 Rx 框架进行异步调用,使用 void AsyncMethod(Action<t> 回调)模式</t>

[英]Using Rx Framework for async calls using the void AsyncMethod(Action<T> callback) pattern

I've seen tons of examples on how to use the Observable.FromAsyncPattern() in the Rx Framework to simplify Async calls, but I'm using an interface that doesn't use the standard Async pattern of IAsyncResult BeginXXX/EndXXX(IAsyncResult), so this doesn't work for me.我已经看到了大量关于如何在 Rx 框架中使用 Observable.FromAsyncPattern() 来简化异步调用的示例,但我使用的接口不使用 IAsyncResult BeginXXX/EndXXX(IAsyncResult) 的标准异步模式,所以这对我不起作用。

The library I'm working with exposes async functions with a callback patter:我正在使用的库公开了带有回调模式的异步函数:

void GetAllObjects(Action<List<Object>> callback)

In an ideal world I'd like to turn this:在一个理想的世界里,我想把这个变成:

var isLoadingUsers = true;
var isLoadingSystems = true;
var isLoadingCustomers = true;
var isLoadingRules = true;

mClient.GetAllUsers(UsersCallback);
mClient.GetAllCustomers(CustomersCallback);
mClient.GetAllRules(RulesCallback);

// set the IsLoadingXXX variables to false in callbacks
// once all are false

mClient.GetAllSystems(SystemsCallback);

into something like this:变成这样的东西:

var o = Observable.ForkJoin(
                     Observable.Start(GetAllUsers()),
                     Observable.Start(GetAllCustomers()),
                     Observable.Start(GetAllRules())
                    ).Finally(() => GetAllSystems);

How would one go about turning that pattern into something that returns an IObservable? go 如何将该模式转换为返回 IObservable 的东西?

Func<IObservable<TRet>> FromListCallbackPattern(Action<Action<List<TRet>>> function)
{
    return () => {
        // We use a ReplaySubject so that if people subscribe *after* the
        // real method finishes, they'll still get all the items
        ret = new ReplaySubject<TRet>();

        function((list) => {
            // We're going to "rebroadcast" the list onto the Subject
            // This isn't the most Rx'iest way to do this, but it is the most
            // comprehensible :)
            foreach(var v in list) {
                ret.OnNext(v);
            }
            ret.OnCompleted();
        });

        return ret;
    };
}

Now, you can do something like:现在,您可以执行以下操作:

var getAllUsers = FromListCallbackPattern(mClient.GetAllUsers);
getAllUsers().Subscribe(x => /* ... */);

Try Observable.Create() , perhaps something like this:试试Observable.Create() ,也许是这样的:

public IObservable<Object> ObserveAllObjects()
{
    return Observable.Create<Object>(
        observer =>
            () => GetAllObjects(objects => objects.ForEach(o => observer.OnNext(o))));
}

I like Observable.Create for this, but @dahlbyk answer is incorrect(misses completion and performs the action in the unsubscribe handler).我喜欢 Observable.Create ,但@dahlbyk 的答案不正确(错过完成并在取消订阅处理程序中执行操作)。 Should be something like this:应该是这样的:

    IObservable<List<T>> FromListCallbackPattern<T>(
        Action<Action<List<T>>> listGetter)
    {
        return Observable
            .Create<List<T>>(observer =>
            {
                var subscribed = true;
                listGetter(list =>
                {
                    if (!subscribed) return;
                    observer.OnNext(list);
                    observer.OnCompleted();
                });
                return () =>
                {
                    subscribed = false;
                };
            });
    }

Also, since the originating API returns an entire list altogether, I don't see a reason to transform it to observable too early.此外,由于原始 API 完全返回整个列表,我认为没有理由过早将其转换为可观察的。 Let the resulting observable return a list as well, and if a caller needs to flatten it, he can use.SelectMany让结果 observable 也返回一个列表,如果调用者需要展平它,他可以使用.SelectMany

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM