我需要进行大量计算。因此,我参考here创建一个简单的加载屏幕。不幸的是,计算完成后会显示加载屏幕。

这是我的代码

class RosterScheduler
{
   .........................
   autoAssign()
   {
    var startDate=parseInt($("#autoPlannStartDate").val());
    var endDate=parseInt($("#autoPlanEndDate").val());
    $("body").addClass("loading");
    if (startDate>endDate)
        alert("Invalid start date or end date selection");
    else
    {
        if (this.rosterTable.haveInvalidPreferredShift(startDate,endDate))
            alert("Invalid shift requirement detected");
        else
        {
            var self=this;
            var finalRoster;
            var roster,tempAverageSD,lowestAverageSD=100.0;

            this.theLowestSDRosters=[];
            this.theLowestMissingShiftRosters=[];
            for (var i=0;i<100;i++)
            {
                this._genRoster(startDate,endDate);
            }
            console.log("Done");
        }
    }
   }
}


我发现,如果我对for循环进行了标记,则加载屏幕可以正常工作。
  如果取消注释for循环,则在控制台中显示“完成”后,将显示加载屏幕。我该如何解决该问题?我试图将函数_genRoster转换为Promise函数,但是它不起作用。

最佳答案

看起来_genRoster阻止了浏览器,直到循环完成,它没有提供任何资源来重新渲染/重新绘制。一种可能性是在给浏览器几毫秒以呈现.loading之后运行循环:

this.theLowestSDRosters = [];
this.theLowestMissingShiftRosters = [];
setTimeout(() => {
  for (var i = 0; i < 100; i++) {
    this._genRoster(startDate, endDate);
  }
  console.log("Done");
}, 50);


在单个requestAnimationFrame之后调用超时为0的函数可能更优雅,从而使浏览器有时间进行重新绘制,然后立即运行重循环:

(警告:以下代码将阻止您的浏览器一段时间)



document.body.style.backgroundColor = 'green';
window.requestAnimationFrame(() => {
  console.log('start, setting timeout');
  setTimeout(() => {
    for (let i = 0; i < 1000000000; i++) {
    }
    console.log('done');
  });
});

08-08 05:04