在嵌套循环中设置间隔

时间:2014-07-24 12:54:12

标签: javascript jquery performance

我在一个函数中有一个嵌套循环,需要一段时间才能在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);

但显然它没有用。

1 个答案:

答案 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);
    })