Pull to refresh

Рекурсивные ajax запросы на jQuery

В моей работе пришлось столкнуться с задачей, когда нужно выполнить секвенцию PUT запросов в определённом порядке, при этом разумеется нужно дождаться выполнения предыдущего запроса. Первое решение было в лоб и я сделал вложенные друг в друга ajax запросы, соответственно при успешном выполнении одного вызывалась функция success в которой был следующий запрос. В самом глубоком (последнем) запросе была функция которая выполнялась по успешному окончанию всей цепочки. Однако взглянув на картину трезвым умом решил переписать код с использованием рекурсии, чем и хотел бы поделиться.

Заводим стек запросов

В моём случае формат предельно прост [url address; value] разные адреса нужны были в моей задаче, т.е. секвенция была из скажем так немного отличающихся друг от друга адресов и значений, туда посылаемых

recursionStack = Array(
{url:"/address/param/1", value: "value1"},
{url:"/address/param/2", value: "value2"},
{url:"/address/param/3", value: "value3"}
);

и так у нас есть стек запросов в той последовательности которая нам нужна

Пишем функцию пост-обработчик

function postFunction()
{
alert("Успешно закончено");
}


Пишем главную рекурсивную функцию

function recursionFunc(postFunc)
{
if (recursionStack.length<=0)
{
eval(postFunc);
return;
}

$.ajax({
type: 'PUT',
url: recursionStack[0].url,
data: recursionStack[0].value,
success: function (){
recursionStack.splice(0, 1);
recursionFunc(postFunc);
},
error: function () {
// можно дописать обработку ошибок на каждой "итерации"
}
});
}


Пишем функцию, которая будет запускать рекурсию

function startProcess()
{
recursionFunc("postFunction();");
}


Код целиком

var recursionStack;

function recursionFunc(postFunc)
{
if (recursionStack.length<=0)
{
eval(postFunc);
return;
}

$.ajax({
type: 'PUT',
url: recursionStack[0].url,
data: recursionStack[0].value,
success: function (){
recursionStack.splice(0, 1);
recursionFunc(postFunc);
},
error: function () {
// можно дописать обработку ошибок на каждой "итерации"
}
});
}

function postFunction()
{
alert("Успешно закончено");
}

function startProcess()
{
recursionStack = Array(
{url:"/address/param/1", value: "value1"},
{url:"/address/param/2", value: "value2"},
{url:"/address/param/3", value: "value3"}
);
recursionFunc("postFunction();");
}

Заключение

Как мы видим происходит следующая логика:
  • вызов функции startProcess(), например по нажатию на кнопку. Инициализируется стек (он же просто массив объектов) с нужными нам элементами. Не забываем объявить переменную стека глобально. Именно в этом весь секрет.
  • Запускаем рекурсию, в качестве параметра передавая название нашей функции пост-обработки, это означает, что когда рекурсия закончится, функция eval её успешно запустит.

Сама же рекурсия вполне статична. Каждый раз берётся первый элемент из стека (естественно пока там есть элементы), затем удаляется первый элемент оттуда. Каждый раз стек уменьшается на еденичку. Когда стек пуст, рекурсия поймёт что пора запускать функцию пост-обработки, запуск контролируется соответственным логическим условием.
Ну вот как-то так. Не претендую на гениальность, но возможно кому-то сама идея поможет в дальнейших или текущих проектах. Работоспособность алгоритма проверил на своей задаче. Проблем не обнаружено. Всем привет.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.