开发者

How do I factor out the callbacks functionality from this ajax function?

I created a reusable ajax pattern in jQuery. It works well, but it's starting to become messy as I add more actions to it.

Look at the success callba开发者_开发百科ck. Every time I add a new action, the conditional logic gets messier: if actionType == foo, then bar etc...

$('.action-panel').delegate('a', 'click', function () {
    var link = $(this),
        actionTypeId = link.data('action-type-id'),

    // Do stuff, like getting the url from the link, etc...
    // Throttle multiple clicks

        $.ajax({ //[snip]

            beforeSend: function () {
                link.toggleClass('on');
            },
            error: function () {
                link.toggleClass('on');
            },
            success: function (response) {
                if (response.success) {
                    if (actionTypeId === 4) {
                        // do stuff for action 4
                    }
                    else if (actionTypeId === 2) {
                        // do stuff related to action 2
                    }
                    else if (actionTypeId === 3) {
                        // do stuff related to action 3
                    }
                    // More action types, etc...
                }
                else {
                    link.toggleClass('on');
                }
            // decide to show tooltip or not
            });
        // do some extra stuff like re-enable the link (throtled earlier)

I should factor out the ajax function by itself. But I can't figure out a way to separate the callback conditionals into their own blocks/functions, and pass back the result.

Any ideas? Please bare in mind I'm new to JavaScript and jQuery.


Have an "action" map like this, saving the action ID and the function to execute:

var actions = {

  '4' : function () {
    $('.fav-count').text(response.newcount);
    $('.fav-count').toggleClass('on');
  },

  '2' : function() {
    link.siblings('.liked').removeClass('on');
    link.siblings('.count').text(response.newcount);
  }
}

Then on the success callback you just do:

if (response.success) {
   actions[actionTypeId]();
}

Note you'll probably have to change a bit things since link wont be visible from the callback but you can do something like actions[actionTypeId](this); and then have the callbacks receive the link as a parameter.


Maybe you could put all the callbacks in a seperate Object:

var success_callbacks = {};
success_callbacks["2"] = function(response) {
    link.siblings('.liked').removeClass('on');
    link.siblings('.count').text(response.newcount);
};
success_callbacks["3"] = function(response) {
    link.siblings('.disliked').removeClass('on');
    link.siblings('.count').text(response.newcount);
};
success_callbacks["4"] = function(response) {
    $('.fav-count').text(response.newcount);
    $('.fav-count').toggleClass('on');
};

And then call them in your success handler

$('.action-panel').delegate('a', 'click', function () {
    var link = $(this),
        actionTypeId = link.data('action-type-id'),

    // Do stuff, like getting the url from the link, etc...
    // Throttle multiple clicks

    // BEGIN AJAX
    $.ajax({
        context: this,
        dataType: 'json',
        url: url,

        beforeSend: function () {
            link.toggleClass('on');
        },
        error: function () {
            link.toggleClass('on');
        },
        success: function (response) {
            if (response.success) {
                success_callbacks[action-type-id](response);
            }
            else {
                link.toggleClass('on');
            }
        // decide to show tooltip or not
        });
    // do some extra stuff like re-enable the link (throtled earlier)


I like to use a switch for this.

switch (actionTypeId) {
case 4:
    $('.fav-count').text(response.newcount);
    $('.fav-count').toggleClass('on');
    break;
case 2:
    link.siblings('.liked').removeClass('on');
    link.siblings('.count').text(response.newcount);
    break;
case 3:
    link.siblings('.disliked').removeClass('on');
    link.siblings('.count').text(response.newcount);
    break;
default:
    break;
}

Note that the first item found true will be executed as long as you have a break in there.

Alternate way: Note the response.success and the NEED for breaks then.

switch (true) {
    case !response.success:
        link.toggleClass('on'); 
        break;
    case actionTypeId===4:
        $('.fav-count').text(response.newcount);
        $('.fav-count').toggleClass('on');
        break;
    case actionTypeId===2:
        link.siblings('.liked').removeClass('on');
        link.siblings('.count').text(response.newcount);
        break;
    case actionTypeId===3:
        link.siblings('.disliked').removeClass('on');
        link.siblings('.count').text(response.newcount);
        break;
    default:
        break;
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜