发出2个可观察量,处理结果然后发出另一个

时间:2014-10-03 13:41:42

标签: java node.js java-8 rx-java vert.x

我要执行以下任务:

我需要发出2个observable(obs1和obs2)来处理它们的结果,然后调用另一个observable(obs3)并处理它的结果,如果可能的话,在处理obs3的结果时可以访问obs1和obs2的结果。

这是我的草案代码,它不能解决问题,我该如何改变它。

public void executeFind(String session_id, long template_id, GameModelType game_model) {

   Observable<RxMessage<byte[]>> userObs = context.getUser(session_id);
   Observable<Game> gameObs = context.findGame(template_id, game_model, GameStateType.WAITING);

   Observable.zip(userObs, gameObs, new Func2<RxMessage<byte[]>, Game, GameObject>() {

     @Override
     public GameObject call(RxMessage<byte[]> userRawReply, ActiveGame game) {

     ..
     ..
     return context.updateGame(game.getGameData())
            .subscribe(new Action1<GameObject>() {

                @Override
                public void call(GameObject updateReply) {
                    ..
                    ..

                }
            });

        return userReply; 
     }
   });
 }

这实际上不起作用 - 我可以编写一个代码,它对每个Observable使用.flatMap \ subscribe的显式调用,但会导致很多嵌套调用,这显然对框架的使用很差。

解决这个问题的正确方法是什么?

谢谢!

修改

我发现这个解决方案可行,但我仍然想知道是否有一种“更清洁”的方法来实现这个目标:

public void executeFind(ReplyMessage<JsonObject> replyObj, String session_id, long template_id,     GameModelType game_model) throws CommandException {

    rx.Observable<GameObject> userObs = context.getUser(session_id);
    rx.Observable<Game> gameObs = context.findGame(template_id, game_model, GameStateType.WAITING);

    rx.Observable.zip(userObs, gameObs, new Func2<GameObject, Game, List<Object>>() {

        @Override
        public List<Object> call(GameObject userReply, Game game) {

            User user = ...;

            final List<Object> results = new ArrayList<Object>(3); 
            results.add(ErrorCodes.STATUS_OK);
            results.add(user);
            results.add(game);


            context.updateGame(game.getGameData()).subscribe(new Action1<GameObject>() {

                @Override
                public void call(GameObject updateReply) {

                    ...
                }

            });


            return results;
        }
    }).subscribe(new Action1<List<Object>>() {

        @Override
        public void call(List<Object> results) {

            int status = (int) results.get(0);
            User user = (User) results.get(1);
            Game game = (Game) results.get(2);

        }

    });
}

1 个答案:

答案 0 :(得分:1)

我会用以下想法编写这个东西。如果map与您的用例相关,则flatMap可以替换为public void executeFind(ReplyMessage<JsonObject> reply_obj, String session_id, long template_id, GameModelType game_model) throws CommandException { Observable<GameObject> userObs = context.getUser(session_id); Observable<Game> gameObs = context.findGame(template_id, game_model, GameStateType.WAITING); Observable.zip(userObs, gameObs, (userReply, game) -> { User user = ...; return GameOfUser.gameFound(game, user); }).map(gou -> { context.updateGame(gou.gameData()).susbcribe(...); return gou; }).subscribe(gou -> ...); } 。另请注意,我只使用了Java 8 lambdas语法,但为了更具可读性,我强烈建议您为每个函数/操作提供简单且命名良好的方法(并将它们与方法引用一起使用),因为它将提高代码的可理解性(那是我们在mockito上做的,但是每个人都应该在自己的代码库中做到这一点)

{{1}}