1

我想在某些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」的小部件的狀態過濾。另一個點擊流的按鈕被過濾到相反的狀態,並被投影到對話框的返回值流中。請注意,對話框的返回值是一個代表給定答案的布爾的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(); 
     }); 

但是,我不喜歡這種解決方案。這對讀者來說並不明顯。

Fortunatly,我找到了另一種解決方案:

 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

我想我找到了一個乾淨的解決方案:

    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(); 
          }); 
+0

這是我也會做的。附: - 嘗試在粘貼前格式化片段,以便它們沒有水平滾動條... – 2011-05-14 21:58:09

相關問題