0

Reactive Extensions を使用して調整された一連の REST API 呼び出しを行うことにより、データを提供するサービス層を構築しようとしています。この質問のために、私は観測可能な Octokit.net ライブラリを使用して、GitHub の REST API からデータを取得しようとしています (Octokit ライブラリの使用方法を選択しないでください)。具体的には、このシナリオでは、ユーザーの詳細、リポジトリのリスト、および ssh キーのリストを取得したいと考えています。したがって、次の操作順序を調整したいと思います。

a. a. ユーザー API を呼び出してユーザーの詳細を取得する b. 結果が来たら、user.Login を取得し、2 つの REST 呼び出しを並行して開始して、リポジトリのリストと ssh キーのリストを取得します。c. リポジトリと 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; }
    }

GithubUserDto1)リポジトリと SshKey への API 呼び出しが独立して非同期モードで終了するときに、アイテムが順番に生成されるようにするにはどうすればよいですか? Zipこのシナリオではオプションではないようです。

GithubUserDto2) 「セカンダリ」API (SshKey など) の 1 つへの呼び出しが非同期に失敗した場合でも (たとえば、ネットワークの問題が原因で)、結果シーケンス内のアイテムの生成を続行するにはどうすればよいですか?

4

1 に答える 1

0

SshKeys と Repositories が 1 つずつ返されているように見えますが、実際に必要なのはリストです。Observableを使用してIObservable<IList<T>>からを取得できます。IObservable<T>ToList

ただし、その前に、エラー ケースを処理する必要があります。単に例外を無視したい場合は、Catchを受け入れる演算子のオーバーロードを使用できますObservable。オブザーバブルをそのオペレーターに渡すことができますEmpty。例外が発生すると、それは無視され、元のソースではなく空のオブザーバブルに切り替わります。

 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 に答える