如何在不冻结浏览器的情况下执行繁重的javascript代码?

如何在不冻结浏览器的情况下执行繁重的javascript代码?,javascript,html,scheduling,freeze,Javascript,Html,Scheduling,Freeze,我有一个页面,加载后执行繁重的javascript代码。为了防止页面在加载时冻结,我将执行分为若干批,中间有一些“不执行”的时间(使用超时),并且运行良好 最近,我不得不添加额外的繁重javascript代码,这些代码可以在客户端操作时执行,但这些操作甚至可以在原始繁重脚本执行完毕之前发生。这一次,间隔操作将没有帮助,因为在一个脚本“停机”时,另一个脚本可以运行,反之亦然,这将导致浏览器冻结 问题实际上更复杂,因为有多个这样的动作,每个动作执行一个不同的重脚本,每个脚本都有一个不同的“优先级”,

我有一个页面,加载后执行繁重的javascript代码。为了防止页面在加载时冻结,我将执行分为若干批,中间有一些“不执行”的时间(使用超时),并且运行良好

最近,我不得不添加额外的繁重javascript代码,这些代码可以在客户端操作时执行,但这些操作甚至可以在原始繁重脚本执行完毕之前发生。这一次,间隔操作将没有帮助,因为在一个脚本“停机”时,另一个脚本可以运行,反之亦然,这将导致浏览器冻结

问题实际上更复杂,因为有多个这样的动作,每个动作执行一个不同的重脚本,每个脚本都有一个不同的“优先级”,与其他脚本相比,我希望它以多快的速度完成

我的问题是,在这种情况下,通常的做法是什么?我试着想办法解决这个问题,但我能想到的只是一个相当复杂的解决方案,就像用javascript编写一个操作系统——也就是说,编写一个“管理器”代码,每X次执行一次(使用“中断”),然后选择要切换到哪个“上下文”(=现在应该运行哪个作业),等等

然而,对我来说,这听起来相当复杂,我希望有其他的解决方案。我的问题听起来像是很多人以前碰到过的问题,所以即使唯一的解决方案是我的建议,我也会假设已经有人写了它,或者有一些图书馆支持这一点

任何帮助都将不胜感激。多谢各位


==编辑==

所谓“繁重的代码”,我指的是大量元素的DOM操作。

您需要考虑将UI/问题域定义为一组异步任务。在我为您制定一个更好的答案之前,这里有更多的见解。

如果您不想阻止脚本,可以使用。请参阅以获得良好的介绍。请注意,web Worker仍然相对较新,大多数浏览器都不支持它

但是,如果您想支持所有浏览器并为“重脚本”添加某种优先级,您应该自己定义一些内容,例如:

function WorkerQueue(this_argument){
    this.queue = [];
    this.this_argument = this_argument;
    this.priority = 1;
}

WorkerQueue.prototype.enqueue = function(callback){
    this.queue.push(callback);
}

WorkerQueue.prototype.dequeue = function(){
    return this.queue.splice(0,1)[0];   
}

function WorkerPool(){
    this.pool = [];
    this.status = "running";
    this.timeout = null;
}

WorkerPool.prototype.addWorker = function(this_argument){
    this.pool.push(new WorkerQueue(this_argument));
    return this.pool[this.pool.length - 1];
}

WorkerPool.prototype.nextTask = function(){
    var max_priority = 0;
    var max_priority_task = this.pool.length;
    for(var i = 0; i < this.pool.length; ++i){
        if(this.pool[i].priority > max_priority && this.pool[i].queue.length !== 0){
            max_priority = this.pool[i].priority;
            max_priority_task = i;
        }
    }
     // pool is empty or all tasks have an invalid priority  
    if(max_priority_task === this.pool.length)
        return;

    if(this.pool[max_priority_task].this_argument)
        this.pool[max_priority_task].dequeue().apply(this.pool[max_priority_task].this_argument);
    else
        this.pool[max_priority_task].dequeue().apply();

    if(this.status !== "running")
        return;
    this.timeout = setTimeout(function(t){return function(){t.nextTask();};}(this),1000);
}

var Workers = new WorkerPool();
var worker1 = Workers.addWorker();
worker1.enqueue(function(){
    console.log("Hello");
});
worker1.enqueue(function(){
    console.log("World");
});

var worker2 = Workers.addWorker();
worker2.priority = 2;
worker2.this_argument = worker2;
worker2.enqueue(function(){
    console.log("Worker 2 - changing priority");
    this.priority = .2;
});
worker2.enqueue(function(){
    console.log("Worker 2 - after change"); 
});

Workers.nextTask();
函数WorkerQueue(此参数){
this.queue=[];
this.this_参数=this_参数;
这个优先级=1;
}
WorkerQueue.prototype.enqueue=函数(回调){
this.queue.push(回调);
}
WorkerQueue.prototype.dequeue=函数(){
返回此.queue.splice(0,1)[0];
}
函数WorkerPool(){
this.pool=[];
this.status=“正在运行”;
this.timeout=null;
}
WorkerPool.prototype.addWorker=函数(此参数){
this.pool.push(newworkerqueue(this_参数));
返回this.pool[this.pool.length-1];
}
WorkerPool.prototype.nextTask=函数(){
var max_priority=0;
var max_priority_task=this.pool.length;
对于(变量i=0;imax_priority&&this.pool[i].queue.length!==0){
max_priority=this.pool[i]。优先级;
最大优先级任务=i;
}
}
//池为空或所有任务的优先级无效
if(最大优先级任务===this.pool.length)
回来
if(this.pool[max\u priority\u task]。this\u参数)
this.pool[max\u priority\u task].dequeue().apply(this.pool[max\u priority\u task].this\u参数);
其他的
此.pool[max_priority_task].dequeue().apply();
如果(this.status!=“正在运行”)
回来
this.timeout=setTimeout(函数(t){return function(){t.nextTask();};}(this),1000);
}
var Workers=new WorkerPool();
var worker1=Workers.addWorker();
worker1.enqueue(函数(){
console.log(“你好”);
});
worker1.enqueue(函数(){
console.log(“世界”);
});
var worker2=Workers.addWorker();
worker2.priority=2;
worker2.this_参数=worker2;
worker2.enqueue(函数(){
日志(“Worker 2-更改优先级”);
这个优先级=0.2;
});
worker2.enqueue(函数(){
控制台日志(“工作人员2-变更后”);
});
Workers.nextTask();


在本例中,每个“繁重脚本”都是一个工作者,基本上是一个任务队列。您可以使用
addWorker
在池中创建一个新的worker,并使用
worker.enqueue(callback)

将任务添加到特定的worker队列中什么类型的“重”javascript?似乎您想在javascript中实现某种分时线程机制,据我所知,Javascript做不到的事情。如果在前端做一些事情需要很长时间(“前端”=您的例子中的Javascript),我通常会坐下来仔细地重新考虑我的应用程序的设计。在这里,您可以使用jquery。使用jqueryajax调用执行大量调用。bPratik:很抱歉,我从来没有像我应该关注的那样关注过网站的这一方面,我会确保它不会再次发生。关于其余的评论:我知道JS中没有线程机制,这就是为什么我要说在单核PC上使用操作系统。在这种情况下,Ajax调用对我没有帮助,因为大部分工作是DOM操作。由于OP编辑了一个问题,澄清了“重代码”是指DOM操作,很有意思的是,WebWorker将如何解决这个问题?将innerHTML发送给WebWorker以进行非DOM文本操作?@Azder:要么这样(WebWorker无法操作DOM内容),要么使用某种调度/自定义工作池。顺便说一句,我在写了我的答案后读了你的链接文章。虽然基本上是相同的方法,但在繁重的任务上使用
setInterval
几乎总是一个坏主意。TBH我只是提供了我得到的第一个google结果,并不是我读到的:)我总是使用setTimeout。至于DOM,就因为我知道它不能操作DOM内容,我写了“将innerHTML发送给WebWorker进行非DOM文本操作”;)