Примечание: извините за количество псевдокода ниже, но я не знал, как еще показать, что я пытаюсь. На самом деле в моем решении намного больше кода, чем в моем решении, управляющем значком ajax и его состоянием, но я изобразил его, чтобы показать корень моей проблемы.
По сути, я пытаюсь создать цикл обработки на веб-странице и считаю, что это очень сложно. Что я хотел бы сделать, это отобразить список транзакций. В верхней части страницы я хочу предоставить пользователю кнопку «Обрабатывать все», которая будет обрабатывать каждую транзакцию по одной за раз. Во время обработки транзакции на сервере пользователь должен иметь возможность отменить цикл обработки. Это просто остановит отправку транзакции NEXT ; очень просто отменить. Тем не менее, из-за асинхронного характера вызовов ajax, я немного борюсь. (
У меня отлично работает в синхронном цикле. Тем не менее, пользователь не может нажать кнопку отмены, используя синхронный подход из-за его однопоточности. Вот что я придумал, пытаясь управлять этим в асинхронном цикле:
<a href="#" id="processAll">Process All</a>
<a href="#" id="cancelProcess">Cancel</a>
<table>
<tr><td><a href="#" id="processLink1">Process</a></td></tr>
<tr><td><a href="#" id="processLink2">Process</a></td></tr>
<tr><td><a href="#" id="processLink3">Process</a></td></tr>
<tr><td><a href="#" id="processLink4">Process</a></td></tr>
</table>
Ниже приведен код, который обрабатывает вышеуказанные ссылки:
var currentId = null;
var isWaiting = false;
var userCancel = false;
$("#processAll").click(function(){
$(this).hide();
$("#cancelProcess").show();
userCancel = false;
// NOTE: this is where I think I need more logic...?
processNextTransaction();
});
$("#cancelProcess").click(function(){
$(this).hide();
$("#processAll").show();
userCancel = true;
});
$("a[id ^= processLink]").click(function(){
var id = $(this).attr("id").replace(/^processLink(/d+)$/, "$1");
doTransaction(id);
});
Ниже приведены вспомогательные методы, которые я использую в трех делегатах выше:
function processNextTransaction()
{
var anchorId = $("a[id ^= processLink]:first").attr("id");
var id = anchorId.replace(/^processLink(/d+)$/, "$1");
function check()
{
if (isWaiting)
setTimeout(check, 500);
else
{
if (!userCancel)
doTransaction(id);
}
}
check();
}
function doTransaction(id)
{
isWaiting = true;
currentId = id;
$.ajax({
type: "POST",
url: "/Transactions/Process/" + id,
data: {},
success: successHandler,
error: failHandler
});
}
function successHander(result)
{
// handle result...
$("#processLink" + currentId).replaceWith(result);
isWaiting = false;
}
function failHandler(result)
{
alert("Error: " + result);
$("#processLink" + currentId).replaceWith("Error!");
isWaiting = false;
}
Обратите внимание, что я звоню processNextTransaction()
только один раз, и это действительно моя главная проблема. Я подумал сделать это из successHandler
и failHandler
, но это противоречит цели флага setTimeout & isWaiting, а также вызывает другие проблемы, когда пользователь нажимает на одну ссылку «Процесс» для обработки одной транзакции. Это мой первый опыт со сценарием Ajax-циклов ... Пожалуйста, помогите! :)
Каков предлагаемый подход для управления списком процессов в асинхронной среде?