我在一个函数中有一个嵌套循环,需要一段时间才能在IE8上加载并导致页面无响应。
我有一个加载栏,它会冻结'当脚本运行时。
如何在每次迭代后使用setInterval()
停止处理JS,以使加载栏仍然移动并使页面显示响应?
功能是:
function createDropDown() {
var target = $('#mainList');
for (var i = 0; i < info.books.length; i++) {
var gnrval = info.books[i].genre
var catval = info.books[i].category
for (var j = 0; j < info.books[i].publishers.length; j++) {
var pubval = info.books[i].publishers[j].publisher
if (typeof app.cache.pub[pubval] == 'undefined') {
app.cache.pub[pubval] = {
'ul': $('<li class="publisher" data-value="' + pubval + '"><a href="#" class="sdeep">' + pubval + '</a><ul class="sub-menu" data-title="Publishers"></ul></li>').appendTo(target).children('ul'),
'aut': {}
};
}
var ulauthors = app.cache.pub[pubval].ul;
for (var k = 0; k < info.books[i].publishers[j].authors.length; k++) {
var autval = info.books[i].publishers[j].authors[k].name + ' (' + gnrval + ')'
var aut_val = info.books[i].publishers[j].authors[k].name
if (typeof app.cache.pub[pubval].aut[autval] == 'undefined') {
app.cache.pub[pubval].aut[autval] = $('<li class="author" data-value="' + autval + '"><a href="#" class="sdeep">' + autval + '</a><ul class="sub-menu" data-title="Authors"></ul></li>').appendTo(ulauthors).children('ul')
}
var ulyears = app.cache.pub[pubval].aut[autval]
console.log(ulyears)
var gItems = []
for (var m = 0; m < info.books[i].publishers[j].authors[k].yearsPublished.length; m++) {
var yearval = info.books[i].publishers[j].authors[k].yearsPublished[m]
var year = ulyears.find('.year[data-value="' + yearval + '"]')
if (year.size() == 0) {
var id = ++count
gItems.push('<li class="year" data-value="' + yearval + '"><a id="selyear' + id + '" class="addone" data-id="' + id + '" data-year="' + yearval + '" data-pub="' + pubval + '" data-aut="' + aut_val + '" data-cat="' + catval + '" data-gnr="' + gnrval + '">' + yearval + '</a></li>')
}
}
ulyears.append(gItems.join(''))
};
};
};
我尝试添加:
setTimeout(function () {
//last nested loop code here
timeout();
}, 1000);
但显然它没有用。
答案 0 :(得分:1)
你应该首先打破这个巨大的功能。简单提示:Principle of single responsibility。
嵌套循环平方完成的操作次数。我建议简化数据,以便可以在一个循环或一系列循环中完成,而不是嵌套循环。这意味着需要取消数据或以一种只需一次通过的方式构建数据。
需要注意的是,数据的大小会增加,因此需要在有效负载大小和处理性能之间进行权衡。这是一个例子,其中一个定位&#34; geo&#34;本书将对第一个数据结构进行多次搜索,但在第二个数据结构上只是一个简单的filter
。
// So you loop through the properties of books, then another loop through math
// then another loop through science, then you get your "geo". Loops: 3
{
books : {
math : ['algebra','trigo','solids'],
science : ['bio','geo','psycho']
}
}
// Here, var geoBook = array.filter(function(book){return book.topic === 'geo'})[0];
// Loops: 1 (filter is essentially a loop)
[
{
type : 'book',
subject : 'math',
topic : 'algebra'
},{
type : 'book',
subject : 'math',
topic : 'trigo'
},{
type : 'book',
subject : 'math',
topic : 'solids'
},{
type : 'book',
subject : 'science',
topic : 'bio'
},{
type : 'book',
subject : 'science',
topic : 'geo'
},{
type : 'book',
subject : 'science',
topic : 'psycho'
},
]
为避免冻结浏览器,您需要&#34;推迟&#34;使用计时器的操作。您可以将setInterval
与计数器一起使用而不是循环。这是一个简单的例子:
function each(array,iterator){
var i = 0, length = array.length;
var timer = setInterval(function(){
iterator.call(array,array[i]);
if(++i >= length) clearInterval(timer);
},1000);
}
each([1,2,3,...10000],function(n){
console.log(n);
})