今天犯了个很有点巧妙的问题,通常而言在开发一个大页面的时候,这里的大页面指的是页面表单控件诸如select中的数据是被动态初始化进去的而不是写死在页面中的,为了提升页面的访问性能,通畅会采用异步的方式去获取,也就是经常看到的显示一个loading...之类的提示,然后ajax异步请求服务器获取数据,加载完成之后,将控件渲染出来。而故事发生的背景,也就是这样的一个应用。
我在页面上有5个select需要进行数据的初始化,同时所在的页面是采用JST动态渲染出来的,所以在进行渲染之前,我希望能将这些数据获取出来并放入模板中以便于之后的渲染。于是写了如下的代码:
NormandyPositionBean.getLastedProducts("proBrand",function(result){_brandlist = result;});
NormandyPositionBean.getLastedProducts("proSize",function(result){_sizelist = result;});
NormandyPositionBean.getLastedProducts("proColor",function(result){_colorlist = result;});
NormandyPositionBean.getLastedProducts("proType",function(result){_typelist = result;});
NormandyPositionBean.getLastedProducts("plicityType",function(result){_policitylist = result;});
var sitem = {"typelist":_typelist,"centlist":_sizelist,"brandlist":_brandlist,"policitylist":_policitylist,"colorlist":_colorlist};
// 增加商品
$("showContent").innerHTML = TrimPath.parseTemplate($("secondToShowGoodManageAdd").value).process(sitem);
// 渲染富文本控件
process();
我先依次异步请求数据,然后放入模板中进行渲染,这样有问题吗?肯定有问题,因为结果显示,那些放入的初始化值,都是空的!那么是怎么回事儿呢?看看代码流程,貌似挺正常的(单纯从java程序员的角度来看)
重新审视了这个过程,蓦然发现自己犯了一个很愚蠢的意识错误,那就是ajax是异步的,而此处的应用却作为同步的方式。
当第一个ajax发出之后,他会继续往下执行代码,而请求返回的时候会自动去执行回调函数,这个过程是错开的,具有一个时间差,上述依次发出了5个请求,然后渲染模板,可是在渲染模板执行的时候,ajax的请求尚未返回,所以得不到数据!
验证方式可以在firefox中开启debug,当请求发出的时候,等待一段时间在继续往下执行,便可以很清楚的了解这个过程。
那么怎么去修正这个问题,那就是采用依次序列化执行的方式来完成:
var sitem = {"typelist":_typelist,"centlist":_sizelist,"brandlist":_brandlist,"policitylist":_policitylist,"colorlist":_colorlist};
// 增加商品
$("showContent").innerHTML = TrimPath.parseTemplate($("secondToShowGoodManageAdd").value).process(sitem);
// 渲染富文本控件
process();
NormandyPositionBean.getLastedProducts("proType",processSelectType);
function processSelectType(result){
var param = {"typelist":result};
$("TypeSelect").innerHTML = TrimPath.parseTemplate($("TypeSelectTA").value).process(param);
NormandyPositionBean.getLastedProducts("proSize",processSelectSize);
}
function processSelectSize(result){
var param = {"centlist":result};
$("SizeSelect").innerHTML = TrimPath.parseTemplate($("SizeSelectTA").value).process(param);
NormandyPositionBean.getLastedProducts("proBrand",processSelectBrand);
}
function processSelectBrand(result){
var param = {"brandlist":result};
$("BrandSelect").innerHTML = TrimPath.parseTemplate($("BrandSelectTA").value).process(param);
NormandyPositionBean.getLastedProducts("plicityType",processSelectPlicity);
}
function processSelectPlicity(result){
var param = {"policitylist":result};
$("PolicitySelect").innerHTML = TrimPath.parseTemplate($("PolicitySelectTA").value).process(param);
NormandyPositionBean.getLastedProducts("proColor",processSelectColor);
}
function processSelectColor(result){
var param = {"colorlist":result};
$("ColorSelect").innerHTML = TrimPath.parseTemplate($("ColorSelectTA").value).process(param);
}
当前一个请求发出并返回之后,继续触发下一个请求,这样控制序列化的请求来完成多个数据的初始化,等所有的请求都完成之后,再进行模板渲染操作即可。