0

我正在尝试构建一个服务层,该服务层通过使用 Reactive Extensions 进行协调的 REST API 调用序列来提供一些数据。为了这个问题,我正在使用 observable Octokit.net 库试图从 GitHub 的 REST API 中提取一些数据(请不要选择 Octokit 库的使用方式)。具体来说,我想在这种情况下检索用户的详细信息、存储库列表和 ssh 密钥列表。所以我想协调以下操作顺序:

一个。通过调用用户 api 来获取用户详细信息 b. 当结果出现时,使用 user.Login 并并行启动两个 REST 调用以检索 repos 列表和 ssh 密钥列表。C。当对 repos 和 ssh 密钥的 api 调用完成时,GithubUserDTO在结果序列中生成一个项目 ( ),其中包含从 a) 和 b) 的 API 结果填充的字段

以下是我到目前为止生成的代码,这似乎是由于Zip.

    public IObservable<GithubUserDto> Get(string username)
    {
        return githubObservableClient.User.Get(username)
            .SelectMany(user =>
            {
                var userRepos = githubObservableClient.Repository.GetAllForUser(user.Login /* for the sake of demo, I assume I don't have user.Login from beginning */);
                var sshKeys = githubObservableClient.SshKey.GetAll(user.Login  /* for the sake of demo, I assume I don't have user.Login from beginning */);

                return userRepos.Zip(sshKeys, (repo, sshkey) =>
                {
                    var userDto = new GithubUserDto() {Id = user.Id, Name = user.Name};
                    userDto.Repositories.Add(repo.FullName);
                    userDto.SshKeys.Add(sshkey.Key.Substring(0, Math.Min(20, sshkey.Key.Length)));
                    return userDto;
                });
            });
    }

GithubUserDto 的样子:

public class GithubUserDto
    {
        public GithubUserDto()
        {
            Repositories = new List<string>();
            SshKeys = new List<string>();
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public List<string> Repositories { get; set; }
        public List<string> SshKeys { get; set; }
    }

1)我如何确保在GithubUserDto对 Repository 和 SshKey 的 API 调用将独立完成并以异步模式完成时,将按顺序生成项目?Zip在这种情况下似乎不是选项。

GithubUserDto2)即使对“辅助”API(如SshKey)之一的调用异步失败(例如由于网络问题),我如何继续生成结果序列中的项目?

4

1 回答 1

0

看起来 SshKeys 和 Repositories 一次返回一个,但您真正需要的是一个列表。您可以通过在 Observable 上使用来IObservable<IList<T>>从 an中获取。IObservable<T>ToList

但在您这样做之前,您需要处理错误情况。如果您只是想忽略异常,可以使用Catch接受Observable. 您可以将Emptyobservable 传递给该运算符,当发生异常时,它将忽略它并切换到空的 observable 而不是原始源。

 public IObservable<GithubUserDto> Get(string username)
{
    return githubObservableClient.User.Get(username)
        .SelectMany(user =>
        {
            var userRepos = githubObservableClient.Repository
                .GetAllForUser(user.Login)
                .Catch(Observable.Empty<Repository>()) // empty if error
                .ToList(); // Put all Repositories into a list

            var sshKeys = githubObservableClient.SshKey
                .GetAll(user.Login)
                .Catch(Observable.Empty<SshKey>()) // empty if error
                .ToList(); // Put all Repositories into a list

            return Observable.Zip(
                userRepos,
                sshKeys,
                (repos, keys) =>
                {
                    return new GithubUserDto() {
                        Id              = user.Id,
                        Name            = user.Name,
                        Repositories    = repos,
                        SshKeys         = keys
                    };
                }
            );
        });
}
于 2014-07-20T16:39:59.380 回答