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;
}
精彩评论