使用ajax调用一次处理多个事务的最佳方法是什么?

时间:2009-12-01 19:25:13

标签: jquery ajax logic

注意:抱歉下面有伪代码的数量,但我不知道如何显示我正在尝试的内容。实际上有很多代码比我管理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()一次,这确实是我的主要问题。我考虑过从successHandlerfailHandler开始,但这违背了setTimeout&amp;的目的。 isWaiting标志,当用户单击单个“进程”链接以处理单个事务时,还会导致其他问题。这是我第一次使用ajax循环场景体验...请帮忙! :)

在异步环境中管理进程列表的建议方法是什么?

2 个答案:

答案 0 :(得分:3)

这应该有效:

<a href="#" id="processAll">Process All</a>
<a href="#" id="cancelProcess">Cancel</a>
<table>
  <tr><td><a href="#" class="processLink" id="pl_1">Process</a></td></tr>
  <tr><td><a href="#" class="processLink" id="pl_2">Process</a></td></tr>
  <tr><td><a href="#" class="processLink" id="pl_3">Process</a></td></tr>
  <tr><td><a href="#" class="processLink" id="pl_4">Process</a></td></tr>
</table>

jQuery魔术:

var cancel = false;

$('#processAll').click(function() {    
    process($('.processLink:first'), true);
    cancel = false;
    return false;
});

$('.processLink').click(function() {
    process($(this), false);
    return false;
});

$('#cancelProcess').click(function() {
    cancel = true;
    return false;
});

function process(el, auto) {

    if(!cancel) {
        var id = parseInt(el.attr('id').replace('pl_', '')); // Get numeric ID

        $.ajax({
           type: "POST",                
           url: "process.php?id=" + id,
           success: function() {
               el.html('Processed');                     
               if(auto) { // If auto is true, process next ID                        
                   if($('#pl_'+(id + 1)).size() > 0) {                             
                       process($('#pl_'+(id + 1)), true);
                   }
               }
           }
       });
    }
}

如果在变量automatic设置为true的情况下调用原始流程函数,则process函数使用success处理程序处理下一个元素。

如果已经开始,取消将不会取消该过程。显然。

您可能需要/需要不同类型的方法来遍历您的流程项,但我想这不是您的问题(这依赖于ID按数字升序排列)。

可在此处找到一个工作示例:http://www.ulmanen.fi/stuff/process.php

答案 1 :(得分:0)

您的代码太长,无法阅读,但根据您的介绍,我会做这样的事情:

创建排队机制(基本上是一个数组)。当用户想要处理某个事务时,将其添加到队列中,并调用一个类似doNextItemInQueue_unlessSomethingAlreadyRunning()的函数。

该函数获取队列中的第一项(基本上是url),发出ajax请求,等待响应,然后再次调用自己。

如果要启用中止队列,请设置一个标志(例如abort_queue),并在doNextItemInQueue_unlessSomethingAlreadyRunning()运行之前进行检查。

相关问题