区分可能的流,寻找一个干净的解决方案

时间:2011-05-14 13:12:05

标签: system.reactive reactive-programming reactive-extensions-js

我正在尝试在某些GUI场景中使用RxJS。我遇到了一个有趣的案例。 我有一个小部件,可以查看,编辑和创建实体。

单击“AddNewEntity”按钮时。 editwidget创建一个空实体,加载它并更改为编辑模式。但是,如果您已经处于编辑模式,那么如果您想首先还原更改,那么请点击“是”,这与前面所述相同。

所以我认为Rx可能会帮助我。这是代码。

        Rx.Observable.Merge([

            editWidget.getObservable('AddNewEntityButtonClicked')
                      .Where(isNotInEditMode),
            editWidget.getObservable('AddNewEntityButtonClicked')
                      .Where(isInEditMode)
                      .Select(function (id) {
                          return dialogWidget.question("Reject Changes?", "You are in edit mode. Reject Changes?")
                            .Where(function (answer) { return answer === true; });
                      })
                      .Switch()
        ])
        .Subscribe(self, function () {
            var entity = createNewEntity();
            editWidget.loadEntity(currentEntity);
            editWidget.setEditMode();
        });

基本上我正在合并两个流。按钮的一个点击流,按状态为“NotInEditMode”的窗口小部件状态进行过滤。对按钮的另一个点击流被过滤到相反的状态加上被投射到对话框的返回值流中。请注意,对话框的返回值是bool的AsyncSubject,它代表给定的答案。

现在是棘手的部分!它不会这样工作!为什么?因为当状态为“NotInEditMode”时,第一个流匹配,它将窗口小部件设置为编辑模式,现在第二个流(由于合并中的顺序而后续运行)也将匹配哪个基本上结果进入完全不一致的状态(解锁编辑模式加上打开对话框)。

我找到了两种解决方法。第一个,更改合并中的顺序,使其看起来像这样:

        Rx.Observable.Merge([
            editWidget.getObservable('AddNewEntityButtonClicked')
                      .Where(isInEditMode)
                      .Select(function (id) {
                          return dialogWidget.question("Reject Changes?", "You are in edit mode. Reject Changes?")
                            .Where(function (answer) { return answer === true; });
                      })
                      .Switch(),
            editWidget.getObservable('AddNewEntityButtonClicked')
                      .Where(isNotInEditMode)                
        ])
        .Subscribe(self, function () {
            var entity = createNewEntity();
            editWidget.loadEntity(currentEntity);
            editWidget.setEditMode();
        });

但是,我不喜欢这个解决方案。这对读者来说并不明显。

幸运的是,我找到了另一个解决方案:

        Rx.Observable.Merge([

            editWidget.getObservable('AddNewEntityButtonClicked')
                      .Where(isNotInEditMode),
            editWidget.getObservable('AddNewEntityButtonClicked')
                      .Where(isInEditMode)
                      .Select(function (id) {
                          return dialogWidget.question("Reject Changes?", "You are in edit mode. Reject Changes?")
                            .Where(function (answer) { return answer === true; });
                      })
                      .Switch()
        ])
        .Take(1)
        .Repeat()
        .Subscribe(self, function () {
            var entity = createNewEntity();
            editWidget.loadEntity(currentEntity);
            editWidget.setEditMode();
        });

背后的想法是只能有一种方法可以让第一种匹配方案中止所有其他方案。

但是,我想知道是否有更清洁的解决方案,或者我是否正在尝试将Rx用于它未设计的东西; - )

1 个答案:

答案 0 :(得分:1)

我想我找到了一个干净的解决方案:

                  editWidget.getObservable('NewButtonClicked')
                            .Select(function () {
                                return isInEditMode() ? dialogWidget.question("Reject Changes", "You are in edit mode. Reject Changes?)
                                                               .Where(function (answer) { return answer === true; }) : Rx.Observable.Return(true);
                            })
                            .Switch()
                            .Subscribe(function(){
                                currentEntity = options.createNewEntity();
                                editWidgetLoadEntity(currentEntity);
                                editWidget.enable();
                            });