jQuery异步函数调用,没有AJAX请求

Sar*_*els 41 javascript forms jquery asynchronous function

这看起来很傻,但我找不到如何使用不涉及某些服务器端请求的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;
});
Run Code Online (Sandbox Code Playgroud)

目前我提交表格并且指标未显示,浏览器冻结,然后slowFunctionCall完成.

编辑:我使用了Vivin的答案,特别是Sitepoint链接来获得以下解决方案:

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);
Run Code Online (Sandbox Code Playgroud)

这会显示和隐藏指示器,也不会冻结浏览器.您可以看到DOM元素在工作时被隐藏,这就是我想要的.

Viv*_*ath 30

Javascript在单个线程中运行,因此如果你的函数很慢,它将阻止其他所有内容.

UPDATE

这将做你想要的一些,但请记住,它们在IE 中不受广泛支持(我认为它们将在IE10中).

Web Worker上的一些资源:

以下是在没有Web工作者的情况下完成多线程的一些资源.重要的是要注意这不是"真正的"多线程:


sli*_*fty 6

我打算建议看一下超时但是唉.John Resig(jQuery)的这篇文章解释了JavaScript如何处理其单线程. http://ejohn.org/blog/how-javascript-timers-work/

本文还解释了:"在JavaScript中异步执行函数时要记住的一件事是,页面中的所有其他JavaScript执行都会暂停,直到函数调用完成.这就是所有当前浏览器执行JavaScript的方式,如果执行JavaScript会导致实际性能问题你试图同时异步调用太多东西.一个长时间运行的函数实际上会"锁定"用户的浏览器.同样的函数调用也是如此."

所有这一切,你可以通过将你正在做的循环分成一个较小的块并使用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)
Run Code Online (Sandbox Code Playgroud)


nwe*_*ome 6

你可能想要网络工作者!

编辑:我很惊讶有多少人跳到"它不可能"所以我会详细说明.Web Workers是HTML 5规范的一部分.它们允许您生成线程以在后台运行脚本而不会阻止UI.它们必须是外部js文件,由它们调用

var worker = new Worker('my_task.js');
Run Code Online (Sandbox Code Playgroud)

并通过活动传达.

  • @Sarah:是的,工作人员不访问DOM,因为DOM不是多线程安全的.所以工作者应该运行硬核计算并让调用者操纵DOM. (2认同)