如何在javascript中快速但不立即添加元素?

如何在javascript中快速但不立即添加元素?,javascript,Javascript,我想用随机顺序的点来填充一个元素。我已经成功地编写了所有的功能,但是我对执行速度不满意 如果我使用while循环添加所有的点,这些点看起来只是同时出现 因此,我使用一个带超时递归调用的函数逐个添加点。另一方面,这看起来太慢了。是否有可能以比循环中慢但比setTimeout()更快的速度运行一系列操作 var-dotCellSize; var初始偏移量; var水平时差; 垂直方向上的var时差; var容器; 红色变种; var点; var newDotElement=$(''); 函数随机整

我想用随机顺序的点来填充一个元素。我已经成功地编写了所有的功能,但是我对执行速度不满意

如果我使用while循环添加所有的点,这些点看起来只是同时出现

因此,我使用一个带超时递归调用的函数逐个添加点。另一方面,这看起来太慢了。是否有可能以比循环中慢但比
setTimeout()更快的速度运行一系列操作

var-dotCellSize;
var初始偏移量;
var水平时差;
垂直方向上的var时差;
var容器;
红色变种;
var点;
var newDotElement=$('');
函数随机整数(最小值、最大值)
{
返回Math.floor(Math.random()*(max-min+1))+min;
}
函数addDots()
{
如果(!点长度)
返回;
var dotIndex=随机整数(0,dots.length-1);
var点=点[点索引];
点拼接(点索引,1);
var列=点%slots水平;
变量行=数学地板(点/槽水平);
变量位置={
左:initialOffset+列*dotCellSize,
顶部:初始偏移量+行*点单元格大小
};
var dotElement=newDotElement.clone().css(位置);
if(-1!=redDots.indexOf(点))
dotElement.addClass('red');
dotElement.appendTo(容器);
setTimeout(函数(){
添加点();
}, 1);
}
函数generateDots(dotContainer、cellSize、numberOfRedDots)
{
容器=点容器;
dotCellSize=细胞大小;
dots=[];
红点=[];
container.find('div.dot').remove();
numberOfRedDots=numberOfRedDots的类型!=“未定义”?numberOfRedDots:3;
initialOffset=数学楼层(dotCellSize/2);
slotsloavely=Math.ceil(container.width()/dotCellSize);
slotsVertical=Math.ceil(container.height()/dotCellSize);
var numberOfSlots=水平槽*垂直槽;
while(点长度<槽数)
点.推(点.长度);
while(redDots.length
.dot{
宽度:4px;
高度:4px;
边界半径:50%;
背景色:#C0E3EA;
位置:绝对位置;
z指数:1;
}
点红{
背景色:#EF3D48;
}
.dot容器{
宽度:420px;
高度:280px;
背景色:#333;
}

不幸的是,事实并非如此,这是因为浏览器引擎决定重新绘制屏幕。在没有超时的情况下,浏览器引擎会识别出它将要进行一系列更新(将点添加到DOM中)。因为重新绘制屏幕的成本很高,它需要一次完成尽可能多的工作,而且,在您的情况下,所有的点都会同时显示出来。添加超时后,对函数的每次调用都会“延迟”以供将来执行

这可能“立即”发生,也可能不会发生,详细解释并不容易,因此我建议观看这段解释JS事件循环的视频,或者阅读一些关于浏览器回流的文章:

在不改变你已经做过的很多事情的情况下,一个解决方案是将一些点分批画在一起。我在函数中添加了一个
for
循环,它将把五个点画在一起。将此值调整为10、20或更高,您将看到点的绘制速度更快。我希望你能找到一个合适的号码。我知道您可能只想加快每个点的绘制速度,但请记住,屏幕具有刷新率,因此您希望例程完成得越快,它们以任何方式成批出现的次数就越多

var-dotCellSize;
var初始偏移量;
var水平时差;
垂直方向上的var时差;
var容器;
红色变种;
var点;
var newDotElement=$('');
函数随机整数(最小值、最大值)
{
返回Math.floor(Math.random()*(max-min+1))+min;
}
函数addDots()
{
如果(!点长度)
返回;
for(设i=0;i<5;i++){
var dotIndex=随机整数(0,dots.length-1);
var点=点[点索引];
点拼接(点索引,1);
var列=点%slots水平;
变量行=数学地板(点/槽水平);
变量位置={
左:initialOffset+列*dotCellSize,
顶部:初始偏移量+行*点单元格大小
};
var dotElement=newDotElement.clone().css(位置);
if(-1!=redDots.indexOf(点))
dotElement.addClass('red');
dotElement.appendTo(容器);
}
setTimeout(函数(){
添加点();
}, 1);
}
函数generateDots(dotContainer、cellSize、numberOfRedDots)
{
容器=点容器;
dotCellSize=细胞大小;
dots=[];
红点=[];
container.find('div.dot').remove();
numberOfRedDots=numberOfRedDots的类型!=“未定义”?numberOfRedDots:3;
initialOffset=数学楼层(dotCellSize/2);
slotsloavely=Math.ceil(container.width()/dotCellSize);
slotsVertical=Math.ceil(container.height()/dotCellSize);
var numberOfSlots=水平槽*垂直槽;
while(点长度<槽数)
点.推(点.长度);
while(redDots.length
.dot{
宽度:4px;
高度:4px;
边界半径:50%;
背景色:#C0E3EA;
位置:绝对位置;
z指数:1;
}
点红{
背景色:#EF3D48;
}
.dot容器{
宽度:420px;
高度:280px;
背景色:#333;
}

不幸的是,事实并非如此,这是因为浏览器引擎决定重新绘制屏幕。在没有超时的情况下,浏览器引擎会识别出它将要进行一系列更新(将点添加到DOM中)。因为重新绘制屏幕的成本很高,它需要一次完成尽可能多的工作
Array.from(document.getElementsByClassName("dot-container")[0].childNodes);
function showDots() {
    var list = Array.from(document.getElementsByClassName("dot-container")[0].childNodes);

    function draw(q) {
        var e;
        for (var i = 0; i < q; i++) {
            if (list.length == 0) {
                return;
            }
            e = list.shift();
            e.style.visibility = "visible";
        }
    }

    function callback() {            
        if (list.length == 0) {
            return;
        }
        draw(4);
        setTimeout(callback);
    }

    callback();
}