Добрый день, коллеги!
В одном из проектов мне потребовалось сохранять выбранные пользователем настройки (сделанные в виде чекбоксов). Поскольку предполагалось, что настройки будут изменяться нечасто — я решил передавать настройки не все сразу, а в виде последовательности изменений. Детали реализации под катом.
Начну с постановки задачи. Есть объект, представляющий из себя набор контактной информации. Пользователь выбирает, в каком виде его сохранять, после чего на сервере происходит преобразование объекта в нужный вид. Но пользователь может захотеть сохранять не всю информацию, а только интересующую его часть. Для этого ему нужно предоставить выбор — что сохранять.
Можно сохранять просто асинхронными AJAX-запросами, но в этом случае может возникнуть не очень приятная ситуация, когда очередное изменение отправилось на сервер — и где-то по дороге застряло, а пользователь уже пытается сохранить контакт. В результате он получит не совсем то, что ожидал. Возникает вопрос — как сделать, чтобы изменения сохранялись строго по порядку. Для этого я решил воспользоваться имеющимися в jQuery очередями.
Очереди в jQuery применяются для реализации анимации и эффектов, но никто не мешает использовать их просто для последовательного выполнения нужных действий. В результате у меня получился примерно такой код:
function ajaxQueue(func){
$(document).queue("ajax",func);
if($(document).queue("ajax").length == 1)
$(document).dequeue("ajax");
}
$(".contact input:checkbox")
.change(function(){
var $_ = $(this),
checked = $_.is(":checked"),
$_.attr("disabled","disabled");
ajaxQueue(function(){
$.post("/ajax/check_elem",
{name: $_.attr("id"),
value: checked})
.error(function(){
$_.val((!checked)?"on":"off");
})
.complete(function() {
$_.removeAttr("disabled");
$(document).dequeue("ajax");
});
});
});
При переключении чекбокса в очередь ставится новый шаг — функция отправки изменения на сервер. Если при этом очередь была пустая, то функция тут же запускается на выполнение (dequeue в функции ajaxQueue). После выполнения имеющегося в функции AJAX-запроса из очереди извлекается очередной шаг и выполняется.
Запрос на сохранение контакта точно так же ставится в очередь и выполняется после того, как все изменения отработали.
function doAction(link){
$.get(link, function(data){
$('body').append(data);
}, 'html');
}
$("a.saveButton")
.click(function(){
ajaxQueue(doAction($(this).attr("href")));
});
PS: В процессе написания этой статьи я пришел к мысли, что все-таки проще передавать все состояния чекбоксов оптом перед сохранением контакта (это к вопросу о том, почему полезно писать статьи :) ), но возможно описанная мной схема кому-нибудь пригодится для других задач.
Автор: gorynych_zmey