在循环中运行javascript时更新网页以显示进度
我已经编写了需要20-30秒处理的javascript,我想通过更新网页上的进度条来显示进度 我使用setTimeout试图允许重新绘制网页 我的代码是这样的:在循环中运行javascript时更新网页以显示进度,javascript,html,settimeout,Javascript,Html,Settimeout,我已经编写了需要20-30秒处理的javascript,我想通过更新网页上的进度条来显示进度 我使用setTimeout试图允许重新绘制网页 我的代码是这样的: function lengthyFun(...){ for(...){ var progress = ... document.getElementById('progress-bar').setAttribute('style',"width:{0}%".format(Math.ceil(progress
function lengthyFun(...){
for(...){
var progress = ...
document.getElementById('progress-bar').setAttribute('style',"width:{0}%".format(Math.ceil(progress)));
var x = ...
// Processing
setTimeout(function(x) { return function() { ... }; }(x), 0);
}
}
它不起作用,我知道它为什么不起作用,但我不知道如何重构代码使其起作用。尝试将
进度元素属性min
设置为0
,max
设置为20000
,值设置为0
;创建函数,其中ifvalue
小于max
incrementvalue
by1000
;利用setTimeout
将持续时间设置为1000
递归调用函数,直到value
达到max
var p=document.querySelector(“进度”);
函数重画(){
如果(p.值
您可能知道,这里的问题是您的主进程(需要很多时间的进程)正在阻止任何渲染。这是因为JavaScript(大部分)是单线程的
在我看来,你有两种解决方法。
第一种方法是将主进程分成不同的部分,并在每个部分之间进行渲染。也就是说,你可以有类似的东西(使用承诺):
您可能需要一个polyfill来实现承诺()。如果您使用jQuery,则它们有一个(糟糕的非标准)实现
第二种解决方案是使用,它允许您在JavaScript中创建线程。它适用于所有现代浏览器。
这可能是对你来说最好的解决方案。
我从来没用过,但你应该可以做这样的事情:
var process = new Worker("process.js");
worker.onmessage(function(event){
updateProgress(event.data.progress)
});
以及process.js中的
postMessage({progress: 0.1});
// stuff
postMessage({progress: 0.4});
// stuff
postMessage({progress: 0.7});
//etc
我知道有几种方法可以通过Javascript触发连续的HTML重画:
- 增量超时时间
- 递归方法调用
第一种也是最简单的方法是在循环的超时时间间隔上使用一个乘法器(比如迭代器)。如果操作独立于外部变量,并且只需要运行有限且相对较少的次数,则此方法就足够了。需要/可能发生的操作越多,对资源的压力就越大——仅用于计算时间间隔。另一个缺点是,当处理时间超过超时时间间隔时,会对观察到的重画间隔造成影响。其结果可能是网页完全冻结,直到所有操作完成
范例
for (var i=0, limit=n; i<limit; i++) {
setTimeout((function(params) {
return function() {
some_func(params);
}
})(param_values), i*1000);
}
var limit = n;
var i = 0;
recursive_timeout();
function recursive_timeout() {
setTimeout((function(params) {
return function() {
some_func(params);
i++;
if (i<limit) {
recursive_timeout();
}
}
})(param_values, i, limit), 1000);
}
虽然增量方法适用于简单任务,但递归将可靠地执行重绘。如果每个操作的处理时间过长是一个问题,那么除了使用递归之外,还值得深入研究异步任务,以避免使网页暂时无法使用
无论如何,希望这有帮助
哈!!刚刚实现的guest271314提供了一个更优雅的递归方法示例。。。哦,好吧,更多的信息不会有什么坏处。你真的在客户身上处理一些事情吗?这需要30秒。“编写了需要20-30秒处理的javascript”可以包括html
,js
,问题是什么,创建stacksnippets,JSFIDLE来演示?请看@ppumkin,是的,我是一个初学者,只是在尝试javascript。该网页未托管,因此没有服务器。这可能是问题所在。JavaScript不应该运行那么长时间!如果您正在使用AJAX,则会显示一个正在加载的GIF或一个简单的进度条,如下所示。要使进度条非常准确,您需要将流程卸载到服务器,实现包含progress percetnage的异步响应。使用jQuery也会帮助您完成分配。@ppumkin为什么不呢?Javascript越来越多地用于功能强大的(web或非web)应用程序。例如,使用客户机执行一些长进程可以避免服务器过载和最小化网络过载。
var limit = n;
var i = 0;
recursive_timeout();
function recursive_timeout() {
setTimeout((function(params) {
return function() {
some_func(params);
i++;
if (i<limit) {
recursive_timeout();
}
}
})(param_values, i, limit), 1000);
}
var still_true = true;
recursive_timeout();
function recursive_timeout() {
some_func(params);
if (still_true) {
setTimeout(function() {recursive_timeout();}, 1000);
}
}