如何在处理完所有其他事件后运行代码

时间:2011-10-13 21:05:56

标签: jquery

我有一个事件处理程序,但我想确保它会等到事件队列中的所有其他事件都执行完毕。

例如,我在页面上有一些标签。我有一些处理标签的通用代码,当用户点击它时,它会将标签设置为“活动标签”。

$('a.tab').click(function() {
  $(this).parent('div').find('a.tab').removeClass('activeTab');
  $(this).addClass('activeTab');
});

对于一组特定的标签,我可能有一个处理程序:

// handler-1
$('div#myTabs a.tab').click(function() {
  do_something();
});

function do_something() {
  var type = $('div#myTabs a.activeTab').data('type');
  do_something_else(type);
}
除了单击选项卡之外,

do_something()可能会响应其他操作而被调用,但无论如何调用它,它都希望知道活动选项卡在继续之前是什么。 < / p>

我的问题是,如果它被'// handler-1'下的代码调用,那么类'activeTab'可能还没有被重置,所以它为'type'检索的值仍然来自于在点击此标签之前选择了标签。

我解决了这个问题:

// handler-1
$('div#myTabs a.tab').click(function() {
  set_timeout( function() {
    do_something();
  }, 100);
});

对于我来说,这看起来太像了。我怎么知道只有在所有其他处理程序轮到他们之后才会调用计时器事件处理程序?当然我可以将“100”更改为“1000”甚至“10000”但我也会更加确定地交易性能(并且仍然没有确定性,因为即使10秒也可能不足以在机器上的浏览器实例上瘫痪了。)

我见过几种可能的解决方案:

但这些都不足以让我满意。我不是想让一个处理程序先运行 。相反,我想要这样的事情:

function do_something() {
  $.when_all_other_events_have_been_handled(function() {
    do_something();
  });
});

这样的事情是否存在?

我看了$ .fn.when(arg).done(),但什么时候?在这种情况下,“arg”必须是一个延迟对象,它执行运行队列中已有的任何内容。 A Catch-22!

Sproutcore有类似“engine.run()”(不记得确切名称)的东西,它只会在“引擎”中的所有其他事件都被处理后返回,但我找不到类似的东西jQuery的。 (http://api.jquery.com/category/events/)。如果有人知道这样的话,请告诉我!

谢谢! :)

2 个答案:

答案 0 :(得分:29)

试试这个:

function postpone( fun )
{
  window.setTimeout(fun,0);
}

因此,如果您致电postpone(do_something);do_something将在postpone()来电之后的事件队列中的所有UI事件之后执行{{1}}。

答案 1 :(得分:27)

我可能在这里找到答案:http://ejohn.org/blog/how-javascript-timers-work/

根据J. Resig的说法,如果我做的话

setTimeout(function() {
  do_something();
}, 0);

匿名函数将立即被访问,但在事件队列中的其他所有内容都已被处理之前不会被调用。也就是说,只要它运行的任何浏览器真正以先进先出的方式运行,就像我期望的那样。如果出于任何原因,Javascript引擎会自行重新排序队列中的事件(我不知道为什么会这样,但是你从来不知道,因为AFAIK我从来没有在标准中看到任何这样的保证,但后来我需要再看一下)然后所有的赌注都关闭了!