最近项目里遇到ajax异步性的问题,简化后的代码如下:
function ajaxGetEvents(calendarView, time) { var year = time.getFullYear(); var month = time.getMonth() + 1 < 10 ? "0" + (time.getMonth() + 1) : time.getMonth() + 1; var day = time.getDate() < 10 ? "0" + time.getDate() : time.getDate(); var timeStr = year + "-" + month + "-" + day; var ajaxData = { search_monthNum : timeStr; }; var ajaxUrl = localStorage.getItem("globalUrl") + 'trip/sheduleInfo!monthList.action'; var eventsData; $.ajax( { type : 'post', dataType : 'json', url : ajaxUrl, data : ajaxData, async: false,//此处设置ajax为同步请求 success : function(data) { if (data.retCode == '1') { eventsData = data.returnData; } else { console.log(data.message); } }, error : function() { console.log('ajax error in calendar.js'); } }); return eventsData; }
这个函数试图将ajax获取到的数据存储到eventsData中,然后返回。
这里主要要注意的是注释处,如果不将这个请求设为同步请求的话,这个返回的数据永远都会是空的。
异步的ajax是非阻塞的,success回调函数只在数据返回后才开始执行,而在此之前,程序会继续运行,执行return语句,那么被返回的eventsData永远是空的。
而同步请求是阻塞的,将这个函数中的请求设为同步则可以解决问题,代价是执行这个函数时可能会需要等待一段时间,时间的长短自然是看响应的速度了。
此外,类似的还有html5中的定位方法geolocation,看下面代码:
$(function(){ var lat, lng; getCurrPosition(); $('#position').html("lat = " + lat + ' lng = ' + lng); function getCurrPosition(){ if(navigator.geolocation){ navigator.geolocation.getCurrentPosition(getPositionSuccess, getPositionError); }else{ alert("您的浏览器不支持Geolocation!"); } } function getPositionSuccess(position) { lat = position.coords.latitude; lng = position.coords.longitude; } function getPositionError(error){ switch (error.code) { case error.TIMEOUT: alert("连接超时,请重试"); break; case error.PERMISSION_DENIED: alert("您拒绝了使用位置共享服务,查询已取消"); break; case error.POSITION_UNAVAILABLE: alert("位置信息不可用"); break; } } });
geolocation中的getCurrentPosition和watchPosition也都是异步的方法,像这个程序试图显示坐标信息的做法也是不可行的,lat和lng会一直为空。
而这里就没办法像ajax一样设为同步了,可行的做法应该是将进行显示的语句$("#position").html()放在getPositionSuccess函数中。