Javascript jQuery 异步函数调用,无 AJAX 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6836299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery asynchronous function call, no AJAX request
提问by Sarah Vessels
This seems silly, but I can't find how to do an asynchronous function call with jQuery that doesn't involve some server-side request. I have a slow function that iterates through a lot of DOM elements, and I want the browser to not freeze up while this function is running. I want to display a little indicator before the slow function is called, then when the slow function returns, I want to hide the indicator. I have the following:
这看起来很愚蠢,但我找不到如何使用 jQuery 执行不涉及某些服务器端请求的异步函数调用。我有一个迭代大量 DOM 元素的慢速函数,我希望浏览器在此函数运行时不会冻结。我想在调用slow 函数之前显示一个小指示器,然后当slow 函数返回时,我想隐藏该指示器。我有以下几点:
$('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;
});
Currently I submit the form and the indicator isn't displayed, the browser freezes, and then slowFunctionCall
is finished.
目前我提交了表单并且没有显示指示器,浏览器冻结,然后slowFunctionCall
完成。
Edit:I used Vivin's answer, specifically the Sitepoint linkto get the following solution:
编辑:我使用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);
This shows and hides the indicator and also doesn't freeze the browser. You get to watch the DOM elements being hidden as it works, which is what I was going for.
这会显示和隐藏指示器,也不会冻结浏览器。你可以看到 DOM 元素在工作时被隐藏,这就是我想要的。
采纳答案by Vivin Paliath
Javascript runs in a single thread and therefore if you have a slow function it willblock everything else.
Javascript 在单线程中运行,因此如果您的功能很慢,它会阻止其他一切。
UPDATE
更新
That will do some of what you want, but keep in mind that they are not widely supportedsupported in IE (I think they will be in IE10).
这会做一些你想做的事情,但请记住,它们在 IE中没有得到广泛支持(我认为它们将在 IE10 中)。
Some resources on Web Workers:
关于 Web Workers 的一些资源:
Here are a few resources on accomplishing multi-threading without web workers. It's important to note that this isn't "true" multi-threading:
这里有一些关于在没有 Web Worker 的情况下完成多线程的资源。重要的是要注意这不是“真正的”多线程:
- Multi-threading in Javascript(title is a little misleading; it's not true multi-threading)
- Why doesn't Javascript support multi-threading?
- Is there some way to do multi-threading in Javascript?
- Simulating multi-threading using IFRAMEs(I'm not sure how viable this method is; it might be more trouble than it's worth and the law of diminishing returns probably applies.)
- Javascript 中的多线程(标题有点误导;它不是真正的多线程)
- 为什么 Javascript 不支持多线程?
- 有什么方法可以在 Javascript 中进行多线程处理吗?
- 使用 IFRAME 模拟多线程(我不确定这种方法的可行性;它可能比它的价值更麻烦,并且可能适用收益递减规律。)
回答by slifty
I was going to suggest looking at a timeout but alas. This post by John Resig (of jQuery) explains a bit about how JavaScript handles its single thread. http://ejohn.org/blog/how-javascript-timers-work/
我打算建议看看超时,但唉。John Resig(来自 jQuery)的这篇文章解释了 JavaScript 如何处理它的单线程。 http://ejohn.org/blog/how-javascript-timers-work/
This articlealso explains: "One thing to remember when executing functions asynchronously in JavaScript, is all other JavaScript execution in the page halts until a function call is completed. This is how all the current browsers execute JavaScript, and can cause real performance issues if you are trying to call too many things asynchronously at the same time. A long running function will actually "lock up" the browser for the user. The same is true for synchronous function calls too."
这篇文章还解释说:“在 JavaScript 中异步执行函数时要记住的一件事是,页面中的所有其他 JavaScript 执行都会暂停,直到函数调用完成。这就是当前所有浏览器执行 JavaScript 的方式,如果你试图同时异步调用太多东西。长时间运行的函数实际上会为用户“锁定”浏览器。同步函数调用也是如此。”
All that said, it's possible you could simulate an asynchronous function call yourself by breaking whatever loop you are doing into a smaller chunk and using setTimeout().
综上所述,您可以通过将您正在执行的任何循环分解为一个较小的块并使用 setTimeout() 来模拟自己的异步函数调用。
For instance this function:
例如这个函数:
// 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)
回答by nwellcome
You might want web workers!
你可能需要网络工作者!
Edit: I'm surprised how many people jumped to "its not possible" so I will elaborate. Web Workers are part of the HTML 5 spec. They allow you to spawn threads to run scripts in the background without blocking the UI. They must be external js files, are invoked by
编辑:我很惊讶有多少人跳到“不可能”,所以我会详细说明。Web Workers 是HTML 5 规范的一部分。它们允许您生成线程以在后台运行脚本而不会阻塞 UI。它们必须是外部js文件,被调用
var worker = new Worker('my_task.js');
and are communicated to via events.
并通过事件进行通信。