2015-03-31 94 views
2

我目前正試圖提高自己的重構技巧,我有一段代碼,我寫了兩個非常相似的方法,並且我試圖圍繞簡化我的頭部臃腫的代碼,任何建議將受到歡迎。試圖瞭解JavaScript中的DRY原理

正如你所看到的,這兩種方法非常相似,唯一真正的區別是POST的URL。

authenticateA : function(e) { 
    var $this = $(e.target).closest('[data-fn]') 
    , text = $this.text() 
    , that = this; 

    $this.text('Authenticating...').addClass("auth-button-disable") 

    $.ajax({ 
    type : 'POST', 
    url : '/A_authentications/update/', 
    data : { _method : 'PUT', sms_token : this.$el.find('#sms-input').val() }, 
    complete: function(xhr) { 

     if (xhr.status === 200) 
     that.relocate(); 
     else { 
     $this.text(text).removeClass("auth-button-disable"); 
     that.handleError(xhr.status); 
     } 
    }, 
    dataType : 'json' 
    }); 
}, 

authenticateB : function(e) { 
    var $this = $(e.target).closest('[data-fn]') 
    , text = $this.text() 
    , that = this; 

    $this.text('Authenticating...').addClass("auth-button-disable") 

    $.ajax({ 
    type : 'POST', 
    url : '/B_authentications/', 
    data : { otp : this.$el.find('#B-input').val() }, 
    complete: function(xhr) { 
     if (xhr.status === 200) 
     that.relocate(); 
     else { 
     $this.text(text).removeClass("auth-button-disable"); 
     that.handleError(xhr.status) 
     } 
    }, 
    dataType : 'json' 
    }); 
} 

我稱之爲一個事件的方法是單擊功能塊:

'click [data-fn="authenticate-A"]' : 'authenticateA', 
'click [data-fn="authenticate-B"]' : 'authenticateB' 

我想這可能是重構爲一個方法或兩個苗條的方法,我只是不知道從哪裏開始,再次感謝提前。

+2

的到重構兩種方法成一個關鍵是確定什麼是兩個並可能這些差異在任何一個功能參數或從DOM元素中指定之間的差異。作爲一個起點,看起來url和類型是不同的,這些值可以來自

標籤本身,然後你可以使用jquery進行檢索。 – hofan41 2015-03-31 17:01:49

+1

與'200'一起使用ajax'complete'方法是多餘的。只需使用'done'方法。 'complete'方法也被棄用。 – vsync 2015-03-31 17:09:15

+1

使用'complete'參數[未棄用](http://stackoverflow.com/a/15821199/2788131)。 '.ajax({})。complete()',方法是。 – D4V1D 2015-03-31 17:13:19

回答

3

你可以有一個生成的函數功能:

var authDetailsA = { 
    url : '/A_authentications/update/', 
    dataFunc : function (this) { 
    return { _method : 'PUT', sms_token : this.$el.find('#sms-input').val() }; 
    } 
}; 
var authDetailsB = { 
    url : '/B_authentications/', 
    dataFunc : function (this) { 
    return { otp : this.$el.find('#B-input').val() }; 
}; 
authenticateA : generateAuthFunction(authDetailsA); 
authenticateB : generateAuthFunction(authDetailsB); 

你可以稱之爲:

generateAuthFunction : function(authDetails) { 
    return function (e) { 
    var $this = $(e.target).closest('[data-fn]') 
    , text = $this.text() 
    , that = this; 

    $this.text('Authenticating...').addClass("auth-button-disable") 

    $.ajax({ 
     type : 'POST', 
     url : authDetails.url, 
     data : authDetails.dataFunc(this), 
     complete: function(xhr) { 

     if (xhr.status === 200) 
      that.relocate(); 
     else { 
      $this.text(text).removeClass("auth-button-disable"); 
      that.handleError(xhr.status); 
     } 
     }, 
     dataType : 'json' 
    }); 
    }; 
} 

然後你生成它它像以前一樣:

'click [data-fn="authenticate-A"]' : 'authenticateA', 
'click [data-fn="authenticate-B"]' : 'authenticateB' 

我認爲這可能會引入不必要的複雜性,但它更幹。

+0

即使在骨幹視圖?你在哪裏調用發電機功能? – 2015-03-31 20:02:44

+1

您可以在之前定義authenticateA和authenticateB函數的地方調用它。如果用前兩個代碼塊替換功能的定義,它將具有相同的效果,authenticateA和authenticateB將像之前一樣定義。 – jstriebel 2015-04-01 01:58:54

+0

啊,我明白了。我想我掛在哪裏是var authDetails塊的位置與所有其他代碼所在的返回Backbone.View.extend塊的關係。 – 2015-04-03 20:34:26

1

嘗試(未測試的代碼):

authenticate: function(t, e) { // t = 'A' || 'B' 
    var $this = $(e.target).closest('[data-fn]') 
    , text = $this.text() 
    , that = this 
    , url 
    , data; 

    $this.text('Authenticating...').addClass("auth-button-disable") 

    // conditionnaly set up your variables 
    if(t == 'A') { 
     data = { _method : 'PUT', sms_token : this.$el.find('#sms-input').val() }; 
     url = '/A_authentications/update/'; 
    } else if(t == 'B') { 
     url = '/B_authentications/'; 
     data = { otp : this.$el.find('#B-input').val() }; 
    } 

    $.ajax({ 
    type : 'POST', 
    url : url, // use them 
    data : data, // use them 
    complete: function(xhr) { 

     if (xhr.status === 200) 
     that.relocate(); 
     else { 
     $this.text(text).removeClass("auth-button-disable"); 
     that.handleError(xhr.status); 
     } 
    }, 
    dataType : 'json' 
    }); 
}, 
+0

你會怎樣稱呼點擊事件? – 2015-03-31 19:55:56

1

您可以只檢查authenticate函數中的data-fn屬性。

authenticate: function (e) {   
     var $this = $(e.target).closest('[data-fn]'), 
      text = $this.text(), 
      that = this; 
     $this.text('Authenticating...').addClass("auth-button-disable"); 
     var fn = $this.data("fn"); 

     switch (fn) { 
      case "authenticate-A": 
       data = { 
        _method: 'PUT', 
        sms_token: this.$el.find('#sms-input').val() 
       }; 
       url = '/A_authentications/update/'; 
       break; 
      case "authenticate-B": 
       data = { 
        otp: this.$el.find('#B-input').val() 
       }; 
       url = '/B_authentications/update/'; 
       break; 

     } 

     $.ajax({ 
      type: 'POST', 
      url: url, 
      data: data, 
      complete: function (xhr) { 

       if (xhr.status === 200) that.relocate(); 
       else { 
        $this.text(text).removeClass("auth-button-disable"); 
        that.handleError(xhr.status); 
       } 
      }, 
      dataType: 'json' 
     }); 


    } 
2
  1. 抽象掉您的要求。將您的應用邏輯混合到您的視圖中只能混淆圖片。讓我們創建一個Authentication模塊:

    var Authentication = (function(Backbone, _) { 
        function whoGoesThere(opts) { 
         opts = _.extend({}, opts, { 
          type : 'POST', 
          dataType: 'json' 
         }); 
    
         return Backbone.$.ajax(opts); 
        } 
    
        return { 
         A: function(data) { 
          data = _.extend({}, data, { 
           _method : 'PUT' 
          }); 
          return whoGoesThere({ 
           url : '/A_authentications/update/', 
           data: data    
          }); 
         }, 
         B: function(data) { 
          return whoGoesThere({ 
           url : '/B_authentications/', 
           data: data    
          }); 
         } 
        }; 
    })(Backbone, _); 
    
  2. 配置你的意見來處理與功能,而不是一個函數名的事件,傳遞自己的價值觀,以適當的方法與前一個模塊,然後委託返回的承諾,共同處理:

    events: { 
        'click [data-fn="authenticate-A"]': function(e) { 
         var promise = Authentication.A({ 
          sms_token : this.$el.find('#sms-input').val() 
         }); 
         this.onAuthentication(e, promise); 
        }, 
        'click [data-fn="authenticate-B"]': function(e) { 
         var promise = Authentication.B({ 
          otp : this.$el.find('#B-input').val() 
         }); 
         this.onAuthentication(e, promise); 
        } 
    } 
    
  3. 處理的承諾(這裏的Ajax對象,但可能是任何東西)

    onAuthentication: function(e, promise) { 
        var $this = $(e.target).closest('[data-fn]') 
        , text = $this.text() 
        , that = this; 
    
        $this.text('Authenticating...').addClass("auth-button-disable"); 
    
        promise.done(function() { 
         that.relocate(); 
        }); 
        promise.fail(function(xhr) { 
         that.handleError(xhr.status); 
        }); 
        promise.always(function() { 
         $this.text(text).removeClass("auth-button-disable");   
        }); 
    } 
    

並且一個演示http://jsfiddle.net/s3ydy3u6/1/