【问题标题】:Simple Javascript update long calculation progress in HTML简单的 Javascript 更新 HTML 中的长计算进度
【发布时间】:2018-09-05 06:28:22
【问题描述】:

我正在运行一个很长的循环,需要报告循环的进度。

var mLog=document.getElementById("log");
for (n = 2; (n<10000 && calc_power<power); n=n*2)
{
  calc_power=chi_power(n,w,df,delta1,alfa);
  var message="n="+n+"<br>";
  window.setTimeout(progress(mLog,message), 0);
}

function progress (mLog,message)
{  
  mLog.innerHTML+=message;
}

我按照建议使用了 window.setTimeout,但 HTML 页面更新仅在循环结束后才完成...

【问题讨论】:

  • 您可能正在使用setTimeout,但这不是“推荐的”。正如所写的那样,您的整个计算必须在其他任何东西有时间运行之前完成,而您最终得到的是一个非常大的微小的 innerHTML 更新队列,等待计算完成后运行。

标签: javascript html logging progress


【解决方案1】:

循环是同步的,所以在setTimeout()中的任何函数被执行之前它会一直运行到结束。

你必须把你的循环变成一个函数,这样它就会使用setTimeout回调自己:

var mLog = document.getElementById("log");

var w, df, delta1, alfa;            // fake implementation, for demo only
function chi_power(n) { return n; } // fake implementation, for demo only

var calc_power = 0, power = 5000;   // fake data, for demo only

function calculate(n) {
  if (n<10000 && calc_power<power) {
    calc_power=chi_power(n,w,df,delta1,alfa);
    var message="n="+n+"<br>";
    progress(mLog,message);

    // proceed with the loop
    setTimeout(function () { calculate(n*2); }, 0);
  }
}

function progress(mLog, message) {
  mLog.innerHTML += message;
}

calculate(2);
&lt;div id="log"&gt;&lt;/div&gt;

【讨论】:

  • 成功了。唯一的问题是计算(2)之后的任何其他活动;在第一次迭代结束后立即开始。所以我把它移到函数calculate(n)中的“else”
  • 没问题!说得通!顺便说一句,我看到您是 JSYK 的新用户,如果问题/答案有效,您可以标记它,以便我们知道它是:meta.stackexchange.com/a/5235/219205
【解决方案2】:

您的循环是同步的,但 setTimeout 函数只会在循环结束后触发,因为调用循环的块仍在堆栈上。如果您想报告多个异步*的进度,setTimeout 可能会起作用,但不要将它用于同步的事情。

您必须定期检查是否满足条件以显示进度,例如在 for 循环中:

if (n % 500 === 0) progress(mLog, message);

【讨论】:

  • 我从这个方法开始,实际上每 n 更新一次,但问题是它只有在完成循环后才更新 HTML。还是谢谢
【解决方案3】:

请用递归检查异步方式:

var mLog=document.getElementById("log");
var n = 2;
function progress (mLog,message)
{  
  mLog.innerHTML+=message;
}
function asyncLoop(n) {
  if(n >=10000) return;
  //calc_power=chi_power(n,w,df,delta1,alfa);
  var message="n="+n+"<br>";
  progress(mLog,message);
  window.setTimeout(asyncLoop(n*2), 0);

}
asyncLoop(n);
&lt;div id = "log"&gt; &lt;/div&gt;

【讨论】:

  • window.setTimeout(n*2, 0); 不起作用。 n*2 不是函数。
  • 抱歉,还是不行。 setTimeout 中的第一项必须是函数本身,而不是传递参数的函数调用。 asyncLoop(n*2) 将被立即调用并评估,然后作为无效参数传递给 setTimeout。
  • 请检查小提琴
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 2016-05-21
相关资源
最近更新 更多