最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How do I update the html displayed for each iteration of a for loop in javascriptjquery? - Stack Overflow

programmeradmin4浏览0评论

How would I have the h1 change for each iteration of the loop? This code now only displays the h1 text after everything is done.

for (i=0; i<array.length; i++) {
  $("body > h1").text("Processing #" + i);
  // things that take a while to do
}

Additional info: if I resize the window as it loops, the html updates.

How would I have the h1 change for each iteration of the loop? This code now only displays the h1 text after everything is done.

for (i=0; i<array.length; i++) {
  $("body > h1").text("Processing #" + i);
  // things that take a while to do
}

Additional info: if I resize the window as it loops, the html updates.

Share Improve this question edited Feb 27, 2013 at 22:33 user1413341 asked Feb 27, 2013 at 22:16 user1413341user1413341 2261 gold badge4 silver badges18 bronze badges 3
  • the browser will not render until you yield control back to it. Which means it will not render until you get out of your for loop. But usually there are tricks to force it to re-render. Though I really remend you rewrite your loop to yield to the browser each iteration and continue afterwards...so the window does not lock up on the user. – Brandon Commented Feb 27, 2013 at 22:23
  • 1 "Though I really remend you rewrite your loop to yield to the browser each iteration and continue afterwards" How do I do that? Thanks. – user1413341 Commented Feb 27, 2013 at 22:28
  • I added an example to my answer. – Brandon Commented Feb 27, 2013 at 22:39
Add a ment  | 

5 Answers 5

Reset to default 7
var array = ['one', 'two', 'three']
var i = 0;

var refreshIntervalId = setInterval(function() {
    length = array.length;
    if (i < (array.length +1)) {
        $("h1").text("Processing #" + i);
    } else {
        clearInterval(refreshIntervalId);
    }
    i++     
}, 1000);

http://jsfiddle/3fj9E/

Use a setInterval with a one-millisecond delay:

var i=0, j=array.length;
var iv = setInterval(function() {
    $("h1").text("Processing #" + i);
    // things that take a while to do
    if (++i>=j) clearInterval(iv);
}, 1);

http://jsfiddle/mblase75/sP9p7/

Sometimes you can force a render by forcing a recalculation of layout

for (i=0; i<array.length; i++) {
  $("body > h1").text("Processing #" + i)
      .width();  // force browser to recalculate layout
  // things that take a while to do
}

It might not work in all browsers.

A better way, that does not block the browser so much:

function doThings(array) {
   var queueWork,
       i = -1,
       work = function () {
          // do work for array[i]
          // ...
          queueWork();
       };

   queueWork = function () {
       if (++i < array.length) {
          $("body > h1").text("Processing #" + i);
          setTimeout(work, 0); // yield to browser
       }
   };
}


doThings(yourArray);

DEMO

I've spent a bit of time working out a jquery function that seems to solve this. Basically, it's a process handler that you can add any number of processes to and then call run to sequentially call these in a asynchronous way.

$.fn.LongProcess = function () {
    var _this = this;
    this.notifications = [];
    this.actions = [];

    this.add = function (_notification, _action) {
        this.notifications.push(_notification);
        this.actions.push(_action);
    };
    this.run = function () {

        if (!_this.actions && !_this.notifications) {
            return "Empty";
        }
        //******************************************************************
        //This section makes the actions lag one step behind the notifications.
        var notification = null;
        if (_this.notifications.length > 0) notification = _this.notifications.shift();

        var action = null;
        if ((_this.actions.length >= _this.notifications.length + 2) || (_this.actions.length > 0 && _this.notifications.length == 0)) 
            action = _this.actions.shift();
        //****************************************************************
        if (!action && !notification) {
            return "Completed";
        }

        if (action) action();        
        if (notification) notification();

        setTimeout(_this.run, 1000); 
        //setTimeout(_this.run,1); //set to 1 after you've entered your actual long running process. The 1000 is there to just show the delay.
    }
    return this;
};

How to use with <h1 class="processStatus"></h1>:

$(function () {
    var process = $().LongProcess();

    //process.add(notification function, action function);
    process.add(function () {
        $(".processStatus").text("process1");
    }, function () {
        //..long process stuff
        alert("long process 1");
    });

    process.add(function () {
        $(".processStatus").text("process2");
    }, function () {
        //..long process stuff
        alert("long process 2");
    });

    process.add(function () {
        $(".processStatus").text("process3");
    }, function () {
        //..long process stuff
        alert("long process 3");
    });

    process.run();
});

if the process is very long you can use this script which shows every notification for a specific time interval.

here is the code..

html

<div id="ccNotificationBox"></div>

css

#ccNotificationBox{
 -webkit-animation-name:;
 -webkit-animation-duration:2s;/*Notification duration*/
 box-sizing:border-box;
 border-radius:16px;
 padding:16px;
 background-color:rgba(0,0,0,0.7);
 top:-100%;
 right:16px;
 position:fixed;
 color:#fff;
}
#ccNotificationBox.active{
 -webkit-animation-name:note;
 top:16px;
}
@-webkit-keyframes note{
0%   {opacity:0;}
20%  {opacity:1;}
80%  {opacity:1;}
100% {opacity:0;}
}

javascript

var coccoNotification=(function(){
var
nA=[],
nB,
rdy=true;
function nP(a){
 nA.push(a);
 !rdy||(nR(),rdy=false);
}
function nR(){
 nB.innerHTML=nA[0];console.log(nA[0]);
 nB.offsetWidth=nB.offsetWidth;//reflow ios
 nB.classList.add('active');
}
function nC(){
 nB.classList.remove('active');
 nB.innerHTML='';
 nA.shift();
 nA.length>0?nR():(rdy=true);
}
function init(){
 nB=document.getElementById('ccNotificationBox');
 nB.addEventListener('webkitAnimationEnd',nC,false);
 window.removeEventListener('load',init,false);
}
window.addEventListener('load',init,false);
return nP
})();

usage

coccoNotification('notification 1');

example

http://jsfiddle/f6dkE/1/

info

the example above is perfect for external js as you use just one global variable which is the name of the function ... in my case coccoNotification

here is a different approach but it does the same

http://jsfiddle/ZXL4q/11/

发布评论

评论列表(0)

  1. 暂无评论