转载请注明出处: http://qiudeqing.com/javascript/2015/06/22/code-refactor.html

不注意代码结构,代码难以理解,修改,维护,结合最近一个需求进行总结。

需求介绍

假设上面是某微博账号开礼盒活动,打开礼盒的逻辑如下(假设用户已登陆):

现有后端接口如下:

关注账号

url: follow.json

返回字段说明:

{
  info: {
    ok: true,
    code: '1',
    msg: 'message'
  },
  data: {}
}

可能返回的结果

code msg 说明
1 sucess 关注成功
2 fail 关注失败

检查关注接口

url: checkFollow.json

返回字段说明:

{
  info: {
    ok: true,
    code: '1',
    msg: 'message'
  },
  data: {}
}

结果说明:

code msg 说明
1 not exist 未关注
2 exist 已关注

领取礼盒

url: opengift.json

返回字段说明:

{
  info: {
    ok: true,
    code: '1',
    msg: 'message'
  },
  data: {
    awardName: '奖品1'
  }
}

结果说明:

code msg 说明
2 success 获得奖品
3 opened 已领取

最直接的方案:

html:

<div class="gift"></div>

javascript(使用jQuery):

$('.gift').on('click', function (e) {
  $.ajax({
    url: 'checkFollow.json' // 检查是否关注
  })
  .done(function (data) {
    switch (data.info.code) {

      // 未关注
      case '1':
        $.ajax({
          url: 'follow.json'
        })
        .done(function (data) {
          switch (data.info.code) {

            case '1':
              $.ajax({
                url: 'opengift.json'
              })
              .done(function (data) {
                switch (data.info.code) {

                  case: '1':
                    console.log(data.data.awardName);
                    break;

                  case: '2':
                    console.log('opened');
                    break;

                }
              });
              break;

            case '2':
              console.log('follow fail');
              break;
          }
        });
        break;

      // 已关注,开礼盒
      case '2':
        $.ajax({
          url: 'opengift.json'
        })
        .done(function (data) {

          switch (data.info.code) {

            case '1':
              console.log(data.data.awardName);
              break;

            case '2':
              console.log('opened');
              break;
          }
        });
        break;
    }
  });
});

上面的代码把所有工作都放到了click监听器中执行,单一满足现在的需求还勉强能接受。但是存在一些问题:

目前简单想到的就是上面这些问题,所以在一开始的时候保持一个良好的代码结构能够让后续维护更加容易。下面是目前个人水平下能够想到的一些重构方法:

下面是修改之后的逻辑:

// 配置参数
var config = {
  // 接口地址
  api: {
    follow: 'follow.json',
    checkFollow: 'checkFollow.json',
    openGift: 'opengift.json'
  }
};

// 封装基础操作
var util = {};

// 空函数,默认参数常用
util.noop = function () {};


/**
 * 检查当前用户是否关注,然后执行对应操作
 * arg {Object} 配置回调,内容见defaults
 **/
util.checkFollow = function (arg) {
  var opt = $.extend({}, util.checkFollow.defaults, arg);

  $.ajax({
    url: config.api.checkFollow,
    data: opt.data
  })
  .done(function (data) {
    switch (data.info.code) {

      case '1':
        opt.onNotFollow(data);
        break;

      case '2':
        opt.onFollowed(data);
        break;
    }
  });
};
util.checkFollow.defaults = {
  data: {},   // 请求接口时带的参数
  onNotFollow: util.noop,    // 没有关注
  onFollowed: util.noop     // 已关注
};


/**
 * 执行关注操作,调用对应回调
 * arg {Object} 设置回调,内容见defaults
 **/
util.follow = function (arg)) {
  var opt = $.extend({}, util.follow.defaults, arg);

  $.ajax({
    url: config.api.follow,
    data: opt.data
  })
  .done(function (data) {
    switch (data.info.code) {
      case '1':
        opt.onSuccess(data);
        break;

      case '2':
        opt.onFail(data);
        break;
    }
  });
};
util.follow.defaults = {
  data: {},
  onSuccess: util.noop,   // 关注成功
  onFail: util.noop      // 关注失败
};

/**
 * 打开礼盒
 * arg {Object} 设置回调和参数
 **/
util.openGift = function (arg) {
  var opt = $.extend({}, util.openGift.defaults, arg);

  $.ajax({
    url: config.api.openGift,
    data: opt.data
  })
  .done(function (data) {
    switch (data.info.code) {

      case '1':
        opt.onSuccess(data);
        break;

      case '2':
        opt.onOpened(data);
        break;
    }
  });
};
util.openGift.defaults = {
  data: {},
  onSuccess: util.noop,   // 获得奖品
  onOpened: util.noop    // 已领取
};


var ctrl = {};

var app = {};

app.init = function () {
  $('.gift').on('click', function (e) {
    util.checkFollow({
      onNotFollow: function () {
        util.follow({
          onSuccess: function () {
            util.openGift({
              onSuccess: function (data) {
                console.log(data.data.awardName);
              }
            });
          }
        });
      },

      onFollowed: function () {
        util.openGift({
          onSuccess: function (data) {
            console.log(data.data.awardName);
          }
        });
      }
    });
  });
};

上面的代码将基本的ajax请求根据接口逻辑进行了一层封装,提高代码复用度,结构也更清晰。基本上可以满足需求了。

但是设置了大量异步回调似乎还有可以优化的地方。

。。