首页 > 解决方案 > Javascript 网页停止运行、无响应/崩溃

问题描述

我遇到了 Javascript 分配任务的问题。基本上我想要完成的是使用 html5 画布的“屏幕保护程序”设计循环。当在 html 中单击一个按钮时,它会运行一个函数,该函数使用随机数生成来决定形状、形状的位置、形状填充颜色和形状描边样式,绘制形状然后再次循环。我目前遇到的问题是单击按钮时,页面(我同时使用 chrome 和 firefox)崩溃。我知道这可能是因为我正在使用循环,所以作为响应,我在函数上延迟了 1.5 秒——但它仍然无法运行。任何有关如何改进这一点的建议将不胜感激。

谢谢 :)

(我尝试将代码缩进 4 个空格,抱歉由于某种原因不起作用..?)

HTML:

<button onclick="Screensaver()">Screensaver</button><br>
<div id="Screensaver">
    <br><button onclick="screenstart()">Start Screensaver</button><br>
    <br><button onclick="screenstop()">Stop Screensaver</button>
</div><br>
<canvas id="myCanvas" width="1000" height="600" style="border:1px solid #47bfff;">
</canvas>

JAVASCRIPT:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var gradient=ctx.createLinearGradient(0,0,canvas.width,0);
//screensaver variables
var loop = 0;
var shapenum = 0;
var fillnum = 0;
var stylenum = 0;
var SS = document.getElementById("Screensaver");
//rectangle
var rectx1 = 0;
var recty1 = 0;
var rectx2 = 0;
var recty2 = 0;
//triangle
var trix = 0;
var triy = 0;
//circle
var circx = 0;
var circy = 0;
var circr = 0;
//radius calculation
var sct = 0;
var scb = 0;
var scl = 0;
var scr = 0;
var scmax = 0;
//SCREENSAVER FROM HERE
SS.style.display = "none";
function Screensaver() {
    if (SS.style.display === "" +
        "none") {
        SS.style.display = "block";
    } else {
        SS.style.display = "none";
    }
}
//loop
function screenstart(){
    loop = 1;
    while (loop = 1){
        setTimeout(screenloop(), 1500);
        screenloop();
    }
}
function screenstop(){
    loop = 0;
}

function screenloop(){
    randcal();
    ifstatements();
}
//just calculations from here on down

标签: javascripthtmlhtml5-canvas

解决方案


正如我在评论中所说,问题出在你的screenstart功能上。实际上有很多错误的地方,但导致浏览器崩溃/冻结的主要问题是循环永远不会真正结束。Javascript 是单线程的,也就是说它一次只能做一件事 - 而循环应该在loop0 时停止(或者如果你正确使用==而不是=),这永远不会发生,因为你的代码卡在一个循环中,screenloop不断执行(同时还安排了越来越多的对该函数的调用,而不是它可以到达它们)。

不过有一个简单的解决方法。将功能缩减为:

function screenstart(){
    loop = 1;
    setInterval(screenloop, 1500);
}

然后在中执行以下操作screenloop

function screenloop(){
    if (loop == 1) {
        randcal();
        ifstatements();
    }
}

最重要的区别是您只需安排screenloop每 1.5 秒运行一次,同时允许其他事件发生,并在必要时允许其他代码运行。包括loop设置为 0 的可能性。每次screenloop运行时,它都会检查这个值,并且只有当值为 1 时才会执行它的工作。


推荐阅读