今天笔者在接手公司一个开发到一半的h5游戏项目时,遇到了一个页面卡死的问题。这个问题竟然没有在控制台或者断点模式下报出任何红色错误提示,只是页面卡死,什么按钮啊、图片都点击不了,没有任何反应。
后来笔者开启断点调试,把问题限制在了XX函数里面。因为断点执行到这个函数的时候,继续按逐行调试时,突然退出了断点模式,即逐行运行的黄色箭头消失不见。
后来笔者逐过程调试跟进了这个函数内部,发现了一个死循环:
//排序操作
var bSorted = true;
var cbLast = cbCardCount - 1
while (bSorted != false){
bSorted = true;
for(var i=0; i < cbLast ; i ++ ){ //当这个循环不进的时候,外部就成为了死循环
if( (cbSortValue[i] < cbSortValue[i+1]) || ((cbSortValue[i] == cbSortValue[i + 1]) &&
(cbCardData[i] < cbCardData[i + 1])))
{
bSorted = false;
let temp=cbCardData[i]
cbCardData[i]= cbCardData[i + 1]
cbCardData[i + 1] = temp;
let temp2=cbSortValue[i]
cbSortValue[i]= cbSortValue[i + 1]
cbSortValue[i + 1] =temp2;
}
}
cbLast = cbLast - 1;
}
当时h5游戏是从公司的lua项目翻译过来的,于是笔者出于好奇之下,去看了原公司的lua项目的相应XX函数:
--排序操作
local bSorted = true;
local cbLast = cbCardCount - 1;
repeat
bSorted = true;
for i=1,cbLast do
if (cbSortValue[i] < cbSortValue[i+1])
or ((cbSortValue[i] == cbSortValue[i + 1]) and (cbCardData[i] < cbCardData[i + 1])) then
bSorted = false;
cbCardData[i], cbCardData[i + 1] = cbCardData[i + 1], cbCardData[i];
cbSortValue[i], cbSortValue[i + 1] = cbSortValue[i + 1], cbSortValue[i];
end
end
cbLast = cbLast - 1;
until bSorted ~= false;
容易看出,在原本的lua项目XX函数中,用的是repeat ... until循环。这个循环是一直执行repeat后面的代码块,直到某个条件成立,跳出循环。
而h5中的javascript中的while循环,则是条件满足时,进入循环。因此循环变了,条件却没有改变,因此成了死循环。这应该是前面某同事的lua - js翻译错误。。笔者将循环改为下面这种方式的时候即可:
//排序操作
var bSorted = true;
var cbLast = cbCardCount - 1
do{
bSorted = true;
for(var i=0; i < cbLast ; i ++ ){
if( (cbSortValue[i] < cbSortValue[i+1]) || ((cbSortValue[i] == cbSortValue[i + 1]) &&
(cbCardData[i] < cbCardData[i + 1])))
{
bSorted = false;
let temp=cbCardData[i]
cbCardData[i]= cbCardData[i + 1]
cbCardData[i + 1] = temp;
let temp2=cbSortValue[i]
cbSortValue[i]= cbSortValue[i + 1]
cbSortValue[i + 1] =temp2;
}
}
cbLast = cbLast - 1;
}while(bSorted == false) //笔者觉得do ... while跟repeat .. until比较配,于是把while循环改为do .. while了,其实真正的变化只是while(bSorted != false)改为了while(bSorted == false)
也正是这个死循环,导致了游戏网页卡死。