【问题标题】:JavaScript for loop with innerHTML not updating during loop execution循环执行期间带有 innerHTML 的 JavaScript for 循环未更新
【发布时间】:2011-12-18 06:27:36
【问题描述】:

我正在遍历一个数组,并且在循环的每次迭代中,我都通过 ajax 调用一个 url。我还想更新一个 .innerHTML 以便它显示以使用户了解正在处理循环的哪个迭代。但是,.innerHTML 仅在脚本完成时显示更新。

如何在循环期间显示此通知?

我也在使用查询 ajax 设置“async: false”。我不想一次处理所有的 ajax 请求,因为它们正在编码 CPU 密集型的视频文件。我也不想锁定浏览器等待同步请求完成。

有没有更好的方法来做到这一点?

我的最终目标是为每组视频按顺序执行 combine.php 脚本,同时向用户显示当前状态指示器,同时在此过程中不锁定浏览器。感谢您的帮助!

代码 sn-p 在这里:

// process the loop of videos to be combined
    var status = document.getElementById('currentStatus');
    for (i=0; i< count; i++) {

        // change the display

        var fields = videos[i].split(":", 2);

        current = i +1;

        currentStatus.innerHTML = "<b>Multi-part Videos:</b>&nbsp;&nbsp;&nbsp; <h3 class='status'>Currently Updating Bout #" + fields[1] + " (" + current + " of " + count + " videos)</h3>";



        // run the combine 
        var dataString = 'videoId='+ fields[0]; 



        $.ajax({  
            type: "POST",  
            url: "combine.php",  
            data: dataString,  
            success: function(txt) {


                //deselect the checkbox

                document.combine.video[selected[i]].checked = false;
            },
            async: false 
        }); 

【问题讨论】:

  • count 和 currentStatus 是在哪里定义的?我想你想要 status.innerHTML 或 $('#currentStatus').html(..) 如果你使用 jquery
  • currentStatus 应该是状态,就像第一行一样。它的工作原理与 currentStatus 相同。 count 在上面定义,然后是复选框数组的长度。因为我只想循环选择的项目。

标签: javascript ajax loops innerhtml


【解决方案1】:

async: false 将挂起整个浏览器,直到 ajax 请求完成。这就是为什么您在每次循环迭代时都看不到页面更新的原因。

同步 ajax 请求通常会导致糟糕的用户体验( 喜欢页面莫名其妙地冻结吗?)并且几乎总是有更好的方法来做到这一点。由于您使用的是 jQuery,Deferred Object API 让这一切变得简单。

【讨论】:

  • 异步:假臭。我知道。我只是没有更好的方法。我会看看 Deferred Object 和 $.when()。
【解决方案2】:

正如其他人所暗示的那样,您的问题是因为 JavaScript 是单线程的 - 当单 JS 线程正在等待您的 ajax 请求返回时,不允许更新 UI。

您可以通过将请求更改为异步并使用回调触发对下一个对象的请求来解决此问题:

// trigger the loop of videos to be combined
var status = document.getElementById('currentStatus');
processVideo( 0 );

function processVideo( index ) {
    var fields = videos[index].split(":", 2);

    currentStatus.innerHTML = "<b>Multi-part Videos:</b>&nbsp;&nbsp;&nbsp; <h3 class='status'>Currently Updating Bout #" + fields[1] + " (" + current + " of " + count + " videos)</h3>";

    // run the combine 
    var dataString = 'videoId='+ fields[0]; 

    $.ajax({  
        type: "POST",  
        url: "combine.php",  
        data: dataString,  
        success: function() {
           processResponse( index);
        },
        async: true
    });
}

function processResponse( index ) {
   // this method is called each time the ajax request finishes
   if (index++ < count) {
      //deselect the checkbox
      document.combine.video[selected[index]].checked = false;

      processVideo( index );
   }
}

【讨论】:

    【解决方案3】:

    如果你想在 async 设置为 true 时一个一个地更新,下一个请求可以放在成功回调函数中。更新状态码也应该在那个函数里面。

    function ajaxRequest(i){
    
            // other processing
            .............
    
            $.ajax({  
                type: "POST",  
                url: "combine.php",  
                data: dataString,  
                success: function(txt) {
    
                    //deselect the checkbox
                    document.combine.video[selected[i]].checked = false;
    
                    // update status
                    currentStatus.innerHTML = .....
                    // make next request
                    if(i<lastOne){
                         ajaxRequest(i+1);
                    }
                },
                async: true
            }); 
    }
    

    【讨论】:

    • 那么,递归。我可以看到这将如何进行异步并使其工作。不过,我不清楚这是否能解决我的状态指示器问题。
    • 这样的事情会为我做的。我最终不得不将更多数据传递给函数以使其正常工作,但这是赢家。它确实解决了我的两个问题。
    猜你喜欢
    • 2011-12-27
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2014-10-07
    • 2020-12-25
    • 1970-01-01
    相关资源
    最近更新 更多