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

Вызов асинхронной функции jQuery, без запроса AJAX

Это кажется глупым, но я не могу найти, как выполнить асинхронный вызов функции с помощью jQuery, который не требует какого-либо запроса на стороне сервера. У меня медленная функция, которая повторяется через множество элементов DOM, и я хочу, чтобы браузер не замерзал во время выполнения этой функции. Я хочу отобразить маленький индикатор перед тем, как вызывается медленная функция, а затем, когда медленная функция вернется, я хочу скрыть индикатор. У меня есть следующее:

$('form#filter', parentNode).submit(function() {
  var form = $(this);
  indicator.show();
  var textField = $('input#query', form);
  var query = jQuery.trim(textField.val());
  var re = new RegExp(query, "i");
  slowFunctionCall(); // want this to happen asynchronously; all client-side
  indicator.hide();
  return false;
});

В настоящее время я отправляю форму, и индикатор не отображается, браузер зависает, а затем slowFunctionCall завершается.

Изменить: Я использовал ответ Vivin, в частности Sitepoint link, чтобы получить следующее решение:

var indicator = $('#tagFilter_loading', parentNode);
indicator.hide();
var spans = $('div#filterResults span', parentNode);
var textField = $('input#query', parentNode);
var timer = undefined, processor = undefined;
var i=0, limit=spans.length, busy=false;
var filterTags = function() {
  i = 0;
  if (processor) {
    clearInterval(processor);
  }
  indicator.show();
  processor = setInterval(function() {
    if (!busy) {
      busy = true;
      var query = jQuery.trim(textField.val()).toLowerCase();
      var span = $(spans[i]);
      if ('' == query) {
        span.show();
      } else {
        var tagName = span.attr('rel').toLowerCase();
        if (tagName.indexOf(query) == -1) {
          span.hide();
        }
      }
      if (++i >= limit) {
        clearInterval(processor);
        indicator.hide();
      }
      busy = false;
    }
  }, 1);
};
textField.keyup(function() {
  if (timer) {
    clearTimeout(timer);
  }
  /* Only start filtering after the user has finished typing */
  timer = setTimeout(filterTags, 2000);
});
textField.blur(filterTags);

Это показывает и скрывает индикатор, а также не затормозит браузер. Вы можете следить за тем, чтобы элементы DOM были скрыты, поскольку они работают, и это то, что я собирался сделать.

4b9b3361

Ответ 1

Javascript запускается в одном потоке, поэтому, если у вас есть медленная функция, он блокирует все остальное.

UPDATE

Это будет делать то, что вам нужно, но имейте в виду, что они не поддерживаются широко поддерживаются, поддерживаемые в IE (я думаю, что они будут в IE10).

Некоторые ресурсы для веб-работников:

Вот несколько ресурсов для выполнения многопоточности без веб-работников. Важно отметить, что это не "правда" многопоточность:

Ответ 2

Я собирался предложить посмотреть таймаут, но, увы. Это сообщение Джона Ресига (из jQuery) немного объясняет, как JavaScript обрабатывает свой единственный поток. http://ejohn.org/blog/how-javascript-timers-work/

В этой статье также объясняется: "Одна вещь, которую следует помнить при выполнении функций асинхронно в JavaScript, - это все другое выполнение JavaScript на странице останавливается, пока вызов функции не будет завершен. Таким образом, все текущие браузеры выполняют JavaScript и могут вызывать проблемы с реальной производительностью, если вы пытаетесь одновременно пересылать слишком много асинхронно. Долгосрочная функция фактически" заблокирует "браузер для пользователя. true для вызовов синхронных функций."

Все, что говорилось, возможно, вы могли бы самостоятельно имитировать асинхронную функцию, разбив любой цикл, который вы делаете на меньший кусок, и используете setTimeout().

Например, эта функция:

// Sync
(function() {
  for(var x = 0; x < 100000; ++x) {console.log(x)}
})()

// ASync
var x = 0;
setTimeout(function() {
   console.log(x++);
   if(x < 100000) setTimeout(arguments.callee, 1);
} ,1)

Ответ 3

Вам может понадобиться веб-работники!

Редактирование: меня удивляет, как многие люди подпрыгивают до "его невозможно", поэтому я уточню. Веб-работники являются частью спецификации HTML 5. Они позволяют вам создавать потоки для запуска сценариев в фоновом режиме без блокировки пользовательского интерфейса. Они должны быть внешними js файлами, вызывается

var worker = new Worker('my_task.js');

и сообщаются через события.