Подтвердить что ты не робот

Как запускать код после обработки всех других событий

У меня есть обработчик событий, но я хочу убедиться, что он будет ждать, пока все остальные события в очереди событий не будут выполнены.

Например, у меня есть несколько вкладок на странице. У меня есть общий код для обработки вкладок, который устанавливает вкладку "Активная вкладка", когда пользователь нажимает на нее.

$('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() может быть вызван в ответ на другие действия, кроме нажатия на вкладку, но независимо от того, как он вызывается, он хочет знать, что представляет собой активная вкладка, прежде чем она сможет продолжить.

Моя проблема в том, что если он вызывается кодом под "//handler-1", класс "activeTab", возможно, еще не был reset, поэтому значение, которое он извлекает для "type", по-прежнему будет из любого тега, который был выбран до нажатия на этот.

Я решил это так:

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

Это похоже на слишком много kludge, чтобы удовлетворить меня. Как я узнаю, что обработчик события таймера будет вызван только после того, как все остальные обработчики поменялись? Конечно, я мог бы изменить "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/). Если кто-нибудь знает о чем-то подобном, пожалуйста, дайте мне знать!

Спасибо!:)

4b9b3361

Ответ 1

Попробуйте следующее:

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

поэтому, если вы вызовете postpone(do_something);, что do_something будет выполняться после всех событий пользовательского интерфейса, которые находятся в очереди событий на момент вызова postpone().

Ответ 2

Возможно, я нашел ответ здесь: http://ejohn.org/blog/how-javascript-timers-work/

Согласно J. Resig, если я делаю

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

анонимная функция будет немедленно появляться, но не будет вызвана, пока все остальные события в очереди событий не будут обработаны. То есть, пока какой-либо браузер работает, он действительно запускает все по принципу "первым в первом", как я ожидал. Если по какой-либо причине механизм Javascript берет на себя обязательство переупорядочивать события в очереди (я не знаю, почему это нужно, но вы никогда не знаете с AFAIK. Я никогда не видел такой гарантии в стандартах, но тогда я нужно снова посмотреть), тогда все ставки отключены!