如何消除/合并这些setTimeout函数?

时间:2011-09-16 13:03:53

标签: jquery jqgrid

related question中,我问过如何过滤到jqGrid中的给定行并自动选择。我目前的解决方案是:

$(function () {
   $('.relatedrecipe').click(function () {
      // store off the value of the related recipe I want to switch to
      var recipe = $(this).data('recipename');
      // clear any filters on the grid
      setTimeout(function () {
         $("#recipegrid")[0].clearToolbar();
      }, 50);
      // set the recipe filter to the related recipe name and trigger the filtering
      setTimeout(function () {
         $('#gs_RecipeName').val(recipe);
         $('#recipegrid')[0].triggerToolbar();
      }, 200);
      // auto-select the first row
      setTimeout(function () {
         var firstRowID = $('#recipegrid').jqGrid('getDataIds')[0];
         $('#recipegrid').setSelection(firstRowId, true);      
      }, 500);
   });
}

喜欢这个解决方案(我就像它为我提供了一个解决方案)是我基本上排队了一堆功能将在50ms,200ms和500ms运行。这似乎是一个潜在的问题解决方案,基于正确的时机,所以我不喜欢它。

我考虑过将这些函数嵌套在另一个函数中,每个函数的时间为50毫秒。类似的东西:

$(function () {
   $('.relatedrecipe').click(function () {
      // store off the value of the related recipe I want to switch to
      var recipe = $(this).data('recipename');
      // clear any filters on the grid
      setTimeout(function () {
         $("#recipegrid")[0].clearToolbar();
         // set the recipe filter to the related recipe name and trigger the filtering
         setTimeout(function () {
            $('#gs_RecipeName').val(recipe);
            $('#recipegrid')[0].triggerToolbar();
            // auto-select the first row
            setTimeout(function () {
               var firstRowID = $('#recipegrid').jqGrid('getDataIds')[0];
               $('#recipegrid').setSelection(firstRowId, true);      
            }, 50);
         }, 50);
      }, 50);
   });
}

这样更好吗?我修改了我的代码以这种方式执行它似乎也可以工作,但是有更好的方法吗?

步骤需要按此顺序进行,但我相信在完成第三部分之前,前两部分中的每一部分都需要一些时间才能完成。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

这样的事情怎么样?

var exec_stack = [];
exec_stack.push(function() { 
    // do stuff 1
});
exec_stack.push(function() { 
    // do stuff 2
});
exec_stack.push(function() { 
    // do stuff 3
});

function run_stack(delay) {
    if (exec_stack.length > 0) {
        exec_stack.pop()();
        setTimeout(function() { run_stack(delay) }, delay);
    }
}
run_stack(50);

http://jsfiddle.net/SJmcG/

当然,您的功能不必是匿名的:

function foo() {
    //do stuff
}
exec_stack.push(foo);

答案 1 :(得分:0)

我的最终答案取决于回答为什么事情必须按顺序发生。

在工具栏活动上看起来很多门:如果是这种情况,最好将工具栏调整为(a)提供一些回调,或者(b)触发一些可以绑定的自定义事件

正如你所推测的那样,依靠时间安排是一个非常糟糕的主意,特别是如果你想要跨浏览器和浏览器负载的一致行为。

答案 2 :(得分:0)

我建议您重写click处理程序,如下所示:

$('.relatedrecipe').click(function () {
    // store off the value of the related recipe I want to switch to
    var recipe = $(this).data('recipename'),
        grid = $grid[0];

    // clear any filters on the grid WITHOUT reloading
    grid.clearToolbar(false);

    // set the recipe filter to the related recipe name
    $('#gs_RecipeName').val(recipe).trigger('change');

   // trigger the filtering
   grid.triggerToolbar();
});

可能在上面的代码中,.trigger('change')的调用是不需要的,您可以删除它。试试吧。

选择我将放置在loadComplete事件处理程序中的第一行网格的代码。在使用数据填充网格后,回调函数loadComplete将被称为

loadComplete: function () {
    var $grid = $(this),
        $firstRowWithData = $grid.find("tr.jqgrow:first");

    if ($firstRowWithData.length > 0) {
        // if at least one row with data filled in the grid
        $grid.jqGrid ('setSelection', $firstRowWithData[0].id, true);
    }
}

getDataIds的使用意味着jqGrid将遍历所有网格行并使用ids填充数组。然后你将只获得数组中的第一个元素。

另一种更有效的方法是使用数据来获取第一行的id只是

loadComplete: function () {
    var $firstRowWithData = this.rows;

    if (this.rows.length > 1) {
        // if at least one row with data filled in the grid
         $(this).jqGrid ('setSelection', this.rows[1].id, true);
    }
}

在代码的最后一个版本中,我使用了this的事实,如果构建网格的<table>的DOM元素。因此this.rows表示<tr>元素的数组(网格的行)。第一个元素this.rows[0]是具有height: 0px的虚拟行,将用于定义列的宽度。第二行(如果存在)this.rows[1]是包含数据的第一行。它的id是rowid。您可以阅读the answer了解更多信息。