【问题标题】:What is the best way to process multiple transactions one at a time using ajax calls?使用 ajax 调用一次处理多个事务的最佳方法是什么?
【发布时间】:2009-12-01 19:25:13
【问题描述】:

注意:对于下面的伪代码数量感到抱歉,但我不知道如何显示我正在尝试的内容。实际上,在我的解决方案中管理 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 和 isWaiting 标志的目的,并且当用户单击单个“处理”链接以处理单个事务时还会导致其他问题。这是我第一次体验 ajax 循环场景......请帮忙! :)

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

【问题讨论】:

    标签: jquery ajax logic


    【解决方案1】:

    这应该可行:

    <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,则流程函数使用成功处理程序来处理下一个元素。

    很明显,如果进程已经开始,取消不会取消它。

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

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

    【讨论】:

    • 感谢您的彻底回复和在线运行示例(哇)。我接受了您的建议,基本上将我的“successHandler”和“failHandler”作为内联方法而不是独立函数移到了 ajax 定义中。我的项目现在运行良好,取消工作!再次感谢。
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-26
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多