Последовательное сохранение настроек с использованием AJAX и очередей jQuery

в 8:14, , рубрики: javascript, jquery, метки: ,

Добрый день, коллеги!

В одном из проектов мне потребовалось сохранять выбранные пользователем настройки (сделанные в виде чекбоксов). Поскольку предполагалось, что настройки будут изменяться нечасто — я решил передавать настройки не все сразу, а в виде последовательности изменений. Детали реализации под катом.

Начну с постановки задачи. Есть объект, представляющий из себя набор контактной информации. Пользователь выбирает, в каком виде его сохранять, после чего на сервере происходит преобразование объекта в нужный вид. Но пользователь может захотеть сохранять не всю информацию, а только интересующую его часть. Для этого ему нужно предоставить выбор — что сохранять.

Можно сохранять просто асинхронными 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

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js