首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使这个可观察到的可重用性更强?

如何使这个可观察到的可重用性更强?
EN

Stack Overflow用户
提问于 2014-07-11 00:12:18
回答 2查看 313关注 0票数 1

这是一个可观察的序列,从web服务中检索分页数据。每个web服务响应都包含一个nextRecordsUrl,它指示从何处获取下一组记录。将可观察到的信息转换为更可重用的东西的最佳方法是什么?

Web服务设置:

代码语言:javascript
复制
var auth = new AuthenticationClient ();
await auth.UsernamePasswordAsync (consumerKey, consumerSecret, userName, password + passwordSecurityToken);
var forceClient = new ForceClient (auth.InstanceUrl, auth.AccessToken, auth.ApiVersion);

可观察的:

代码语言:javascript
复制
var observable = Observable.Create<QueryResult<Account>> (async (IObserver<QueryResult<Account>> o) =>
{
    try
    {
        var queryResult = await forceClient.QueryAsync<Account> ("SELECT Id, Name from Account");
        if (queryResult != null)
        {
            o.OnNext (queryResult);

            while (!string.IsNullOrEmpty (queryResult.nextRecordsUrl))
            {
                queryResult = await forceClient.QueryContinuationAsync<Account> (queryResult.nextRecordsUrl);
                if (queryResult != null)
                {
                    o.OnNext (queryResult);
                }
            }
        }
        o.OnCompleted ();
    }
    catch (Exception ex)
    {
        o.OnError (ex);
    }

    return () => {};
});

订阅可观测结果并收集结果:

代码语言:javascript
复制
   var accounts = new List<Account> ();
    observable.Subscribe (
        observer => accounts.AddRange (observer.records),
        ex => Console.WriteLine (ex.Message),
        () => {});

编辑:使用Brandon的解决方案我现在可以用聚合生成结果列表

代码语言:javascript
复制
List<Account> accounts = await forceClient.QueryPages<Account> ("SELECT Id, Name from Account")
                .Aggregate (new List<Account> (), (list, value) =>
                {
                    list.AddRange (value.records);
                    return list;
                });
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-11 18:24:54

信不信由你,Rx-经验库(也由MS维护)有一个名为Expand的操作符。展开用于从一个可观测的元素中获取每个元素,并通过一个函数运行它,该函数产生另一个可观察到的相同类型的元素。这个可观察到的东西会被压平到原来的地方,每一项都会经历相同的过程。

想象给一个树节点一个可观察到的子节点。您可以使用展开来轻松遍历这棵树。由于链接列表只是树的一个受约束的版本,而且由于您所拥有的实际上是一个链接列表,其中每个节点都是可观察的,所以可以使用展开。

代码语言:javascript
复制
public static IObservable<QueryResult<TResult>> QueryPages<TResult>(this ForceClient forceClient, string query)
{
    return Observable.FromAsync(() => forceClient.QueryAsync<TResult>(query))
        .Where(QueryResultIsValid)
        .Expand(result =>
            Observable.FromAsync(() => forceClient.QueryContinuationAsync<TResult>(queryResult.nextRecordsUrl))
                .Where(QueryResultIsValid)
        );
}

public static bool QueryResultIsValid(QueryResult<TResult> result)
{
    return result != null;
}
票数 2
EN

Stack Overflow用户

发布于 2014-07-11 03:05:20

这就是你要找的东西吗?

代码语言:javascript
复制
public static IObservable<QueryResult<TResult>> QueryPages<TResult>(this ForceClient forceClient, string query)
{
    return Observable.Create<QueryResult<T>> (async (observer, token) =>
    {
        // No need for try/catch.  Create() will call OnError if your task fails.
        // Also no need for OnCompleted().  Create() calls it when your task completes
        var queryResult = await forceClient.QueryAsync<TResult> (query);
        while (queryResult != null)
        {
            observer.OnNext (queryResult);

            // check the token *after* we call OnNext
            // because if an observer unsubscribes
            // it typically occurs during the notification
            // e.g. they are using .Take(..) or
            // something.
            if (string.IsNullOrEmpty(queryResult.nextRecordsUrl) ||
                token.IsCancellationRequested)
            {
                break;
            }

            queryResult = await forceClient.QueryContinuationAsync<TResult> (queryResult.nextRecordsUrl);
        }
        // No need to return anything.  Just the Task itself is all that Create() wants.
    }
});

// Usage:
var forceClient = // ...
var foos = forceClient.QueryPages<Foo>("SELECT A, B, C FROM Foo");

注意,我将其切换到提供取消令牌的重载,以便如果观察者取消订阅,您就可以停止获取页面(即使观察者已经停止侦听,您的原始版本也会继续获取页面)。还请注意,异步Create正在等待您的Task,并为您调用OnErrorOnCompleted,所以大多数时候您不需要担心这个问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24688272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档