日常问题总结(ajax异步问题)

来源:互联网 发布:vb趣味程序集锦 编辑:程序博客网 时间:2024/05/18 21:11

前言

  ajax是一种网页开发技术,用于创建快速动态网页,使网页实现异步更新。即不加载整个页面,只对网页的部分元素进行更新。

问题

 ajax功能虽强大,但使用不当,会在开发中造成许多匪夷所思的问题,这里就列举自己在工作中遇到的两个十分典型的问题作为参考。
 众所周知,js是解释型的脚本语言,解释器会由上至下逐行将js代码翻译成二进制文件运行,为了便于理解,这里姑且就将这个过程称之为‘运行的主线程’,而ajax的诞生使得了js具备了异步执行代码的能力,相当于可以创建‘分支线程’了,而下面这个问题就是由于两‘线程’竞争导致的。

多请求竞争

 这个是笔者还是实习生的时候碰到的问题。一个很常见显示地区选择下拉框,第一个下拉框显示省列表,第二个显示市列表,第三个显示城区列表,当改变省时,市列表以及城区列表都会被重置,同理,改变市,城区列表也会被重置。其中省列表的数据是页面加载直接从后台得来,而市列表与城区列表通过ajax做异步请求得到。编码目的是要做一个定制化,点开的时候直接显示浙江省舟山市如图:
这里写图片描述

 现在让我们一起看看代码,根据省级id获取城市名函数如下:

function getCitysByProvinceId(provinceId) {    if(provinceId==1010) {    //这里的ajax请求获取城市列表        jQuery.post("{:U(APP_NAME.'/Register/getCitysByProvinceId')}",{'provinceId': provinceId},function (re) {            var data = jQuery.evalJSON(re);            var opt = '';            //这段代码让舟山市直接在市级列表头显示            for (var i = 0; i < data.length; i++) {                if(data[i]['areaName']=="舟山市"){                    opt += '<option selected="selected" value="' + data[i]['id'] + '">' + data[i]['areaName'] + '</option>';                }else{                    opt += '<option value="' + data[i]['id'] + '">' + data[i]['areaName'] + '</option>';                }            }            //这段代码的作用就是改变省时,重置城市与城区。并擦除列表头            jQuery('#school_city > option:gt(0)').remove();            jQuery('#school_district > option:gt(0)').remove();            jQuery('#school_school > option:gt(0)').remove();            jQuery("#show_schools").html('');            jQuery('#school_city').append(opt);        });    }else{    //和上面一模一样的操作,只不过未做定制化,点开其他省时,取的该省下面的城市列表        jQuery.post("{:U(APP_NAME.'/Register/getCitysByProvinceId')}", {'provinceId': provinceId}, function (re) {            var data = jQuery.evalJSON(re);            var opt = '';            for(var i =0;i<data.length;i++){                opt += '<option selected="selected" value="' + data[i]['id'] + '">' + data[i]['areaName'] + '</option>';            }            //改变省时,重置城市列表,擦除市级和区级列表头            jQuery('#school_city > option:gt(0)').remove();            jQuery('#school_district > option:gt(0)').remove();            jQuery('#school_school > option:gt(0)').remove();            jQuery("#show_schools").html('');            jQuery('#school_city').append(opt);            jQuery('#citySelect').attr({selected : "selected"});        });    }};

 通过城市id获取该城市下的城区列表函数如下:

function getDistrictByCityId(cityId) {//ajax请求得到该城市下的城区列表    jQuery.post("{:U(APP_NAME.'/Register/getDistrictByCityId')}", {'cityId':cityId}, function(re){        var data = jQuery.evalJSON(re);        var opt = '';        for(var i=0; i < data.length; i++) {            opt += '<option value="' + data[i]['id'] + '">' + data[i]['areaName'] + '</option>';        }        //改变城市的时候重置城区列表,擦除区级列表头        jQuery('#school_district > option:gt(0)').remove();        jQuery('#school_school > option:gt(0)').remove();        jQuery("#show_schools").html('');        jQuery('#school_district').append(opt);    });}

 一开始我的思路很简单,先取城市列表,再取城区列表,代码如下:

getCitysByProvinceId(1010);getDistrictByCityId('1095');

 这样做存在一个很大的问题,老手一眼就可以看出来什么问题,两个ajax请求快慢不一,如果第二个获取市区列表的请求先跑完,由于获取城市列表函数中有个重置市区和城区的操作,这个操作会擦除掉你想在市区列表显示的舟山市。而如果第一个请求先跑完,那么这么做一点问题都没有。正是因为两个请求时快时慢导致幽灵时灵时不灵。最后还是叫个老手‘一眼看出来’的。

解决方法

 解决方法老鸟略带鄙视地一句话,将第二个函数放在第一个函数的回调函数里。问题解决。

单请求等待

 这次写了一个手机号验证函数,这个函数里面有一个ajax请求用于判断注册的手机号是否被占用,最后返回一个标志位ret赋值给一个变量。代码比较简单,这里就不过多解读了。具体代码如下:

Register.checkPhone = function(user_phone){        var ret = null;        var phoneNum = jQuery.trim(user_phone);        var roleType = jQuery("#role_type").val();        // 身份证检测        if(phoneNum == ''){            var tip = '';            if(roleType=='teacher'||roleType=='instructor'){                tip = "手机号不能为空!";            }else{                tip = "如没有,请填家长的手机号!";            }            RCommon.showError('tip_phone',tip);            ret = false;        }else{            // 格式检测            var reg = /(^1[3|4|5|7|8][0-9]{9}$)/;            var msg = '手机号码为11位!';            if(phoneNum.length != 11){                RCommon.showError('tip_phone', msg);                ret = false;            }else{                var result = reg.test(phoneNum);                msg = '手机号码格式不正确!';                if(!result){                    RCommon.showError('tip_phone', msg);                    ret = false;                }else{                    jQuery.ajax({                        url : 'index.php?app=' + APP_NAME + '&mod=Register&act=checkPhone',                        type : 'post',                        data : {phone:phoneNum},                        success : function(result){                            var rest = eval('('+result+')');                            if(rest.statuscode=='200'){                                RCommon.showPass('tip_phone','');                                ret = true;                            }else if(rest.statuscode=='400'){                                RCommon.showError('tip_phone','该手机号已被注册!');                                ret = false;                            }                        }                    });                }            }        }        return ret;    }

 废话不多说,直接抛问题,同样是老鸟一眼看出来的问题,由于这个问题出现的时候已入职三个月,所以这次一眼就看出来了,这样将函数的返回值直接赋值给一个全局变量,这个值永远是空(ajax之前的流程都正常)。因为ajax还在跑的过程中,函数已经将ret返回了,而ret的初始值就为null。这个问题和上面的问题有点不同,这次需要‘主线程’去等待‘分支线程’跑完了之后再接着运行程序。那么该怎么做呢?

解决方法

 懂了是什么问题之后,一切就好办多了(好百度),jquery的ajax方法有个参数async,这个参数就是用来控制ajax请求为异步请求还是同步请求,默认是异步的,我们将其设置为同步的即async: false。这样做会让ajax请求结束了之后才执行之后的代码,问题解决。

总结

 ajax真的很强大,但是强大的同时也难免会带来一些匪夷所思的问题。。。。编不下去了=_=||,这里只想让那些同为js菜鸡的同仁,一旦遇到这种数据性时灵时不灵的问题,看看那函数中有没有ajax吧。。。。

0 0
原创粉丝点击