含简单链式调用的ajax类库思路及写法

在写类库前 我们一定要理清楚我们写的类库,传递的参数代表什么意思
然后在封装的时候,首先考虑的就是兼容性的问题,整体的构思
我的整体的代码分3个模块,
1:ajax核心模块;
2:util帮助库(用来解决兼容性问题)
3:链式写法Promise(由于本人对链式写法研究有限,故只能链式调用两个)
在ajax核心模块方面,主要是对ajax里面传递进来的参数进行了统一处理
如是否走缓存,是否是get系的方法,发送的数据如何处理等,统一的都在ajax核心模块里面处理,然后再调用ajax的4部曲 完成数据交互
具体代码及详细注释如下

/**
 * Created by pengrongshu-pc on 2015/9/20.
 */
(function () {
    if (this.$http)return;
    this.$http = function (setting) {
        if(!util.isObject(setting))return;
        //设置默认值
        var defaultOption={
            type:'GET',//设置交互方式
            url:'',
            data:'',
            cache:false,//默认不走缓存
            async:true,//默认为异步方式
            username:undefined,
            password:undefined,
            header:{},//默认为空 看用户 需不需要设置头信息
            success:function(){},//AJAX请求成功就执行
            error:function(){},//ajax请求失败执行
            beforeSend: function () {
            },//在发送前执行
            complete: function () {
            },//完成就执行
            contentType: 'application/x-www-form-urlencoded',//给form表格用的
            mimeType: '',//一个mime类型用来覆盖XHR的 MIME类型
            statusCode: {},//状态码
            timeout: 0,//规定响应完成的最大时间
            context: window,//上下文
            dataType: 'text'//传进来的data是什么数据格式的
        },tempVal;
        //遍历默认值
        util.traverse(defaultOption,function(key){
            defaultOption[key]=setting[key]||defaultOption[key]
        });
        //获取XHR
        var deferred=new Deferred();
        var xhr=util.getXhR();
        //处理 传递进来的参数 所要对应的操作
        //如果不走缓存 我就在url后面加个随机数
        //那么 就要判断url  有没有问号
        if(!defaultOption.cache){
            defaultOption.url=util.hasQuestionMark(defaultOption.url,'_='+(Math.random() * 0xffffff | 0))
        }
        //处理data前 要处理指定方法是什么类的get 或者post处理不同
        var methodReg=/^(get|post|delete|put|head)$/igm;
        //判断处理进来的f方法是否合法、
        if(!(methodReg.test(defaultOption.type))){
            throw  new Error('data Parameter error');
        }
        //不管是get系还是post系 都要转成uri格式 只是放的位置不同 data前提要是对象
        if(util.isObject(defaultOption.data)){
            tempVal=[];
            util.traverse(defaultOption.data,function(key,value){
                tempVal.push(encodeURIComponent(key)+'='+encodeURIComponent(value));
            });
            //将data改变为uri格式了
            defaultOption.data=tempVal.join('&')
        }
        //判断是不是get系
        var getReg=/^(get|put)$/igm;
        if(getReg.test(defaultOption.type.toLocaleLowerCase())){
            //说明是get系 get系将 数据放置到url后面 xhr.send 是不需要传递参数的data就可以清理了
            defaultOption.url=util.hasQuestionMark(defaultOption.url,defaultOption.data);
            defaultOption.data=void 0;
        }

        //处理完参数 开始ajax核心
        xhr.open(defaultOption.type,defaultOption.url,defaultOption.async,defaultOption.username,defaultOption.password);
        /*这里不懂跟后台怎么用*/
        defaultOption.contentType && (defaultOption.header['content-type'] = defaultOption.contentType);
        //自定义头信息
        util.traverse(defaultOption.header, function (key, value) {
            xhr.setRequestHeader && xhr.setRequestHeader(key, value);
        });
        /*这里不懂怎么跟后台用  结束*/
        //改变this关键字
        defaultOption.success=util.bind(defaultOption.success,defaultOption.context);
        defaultOption.error=util.bind(defaultOption.error,defaultOption.context);
        //成功失败统一处理
        var __suc = function (context, headers) {
            defaultOption.success(context, headers);
            defaultOption.complete(context, headers);
            deferred.promise.onsuccess(context,headers);
        };
        var __err = function (status, headers) {
            defaultOption.error(status, headers);
            defaultOption.complete(status, headers);
            deferred.promise.onerror(status,headers)
        };
        // 重写mime类型
        defaultOption.mimeType && xhr.overrideMimeType(defaultOption.mimeType);
        // 开始ajax 处理
        xhr.onreadystatechange=function(){
            //readyState 分4个阶段 =4即 ajax完成 只是说ajax流程走完了
            if(xhr.readyState===4){
                //获取不同的状态码  不同的状态码 对应不同 的操作
                //这个是我们用户自己传递的方法
                tempVal=defaultOption.statusCode[xhr.status];
                util.isFunction(tempVal)&&tempVal();
                //获取后台返回的数据
                tempVal=xhr.responseText;
                //再判断成功与否
                if(/^2\d{2}$/.test(xhr.status)){
                    //2开头表示成功,再判断返回的是否是一个json
                    if(defaultOption.dataType.toLocaleLowerCase()==='json'){
                        try{
                            tempVal=util.parse(tempVal);
                        }catch(err){
                            defaultOption.error(arguments);
                        }
                    }
                    //将获取到的数据和头信息 返回给成功函数 成功函数 里面 怎么做 是由我们自己决定的
                    __suc(tempVal,xhr.getAllResponseHeaders());
                }
            }
        }
        //ajax 请求是否超时判断
        if(defaultOption.timeout>500){
            //最慢也要五百毫秒用
            if('timeout'in xhr){
                //判断xhr 里面有没有 timeout属性
                xhr.timeout=defaultOption.timeout;
                xhr.ontimeout=function(){
                    //超过规定的时间 不管有没有完成 我们都报一个失败回去
                    __err(arguments);//你想给失败传什么就传什么
                }
            }else{
                //没有就是低版本浏览器
                window.setTimeout(function(){
                    if(!xhr.readyState==4){
                        //强制结束ajax
                        xhr.abort();
                        //再报一个失败回去
                        __err(arguments);
                    }
                },defaultOption.timeout)
            }
        };
        defaultOption.beforeSend(xhr);//在发送前执行,具体执行什么操作 由我们自己决定
        xhr.send(defaultOption.data);
        //以上ajax 全部完成
        //供链式写法用
        return deferred
    }
    util = {
        parse:(function(){
            if(window.JSON){
                return function(text){
                    return JSON.parse(text);
                }
            }
            return function(text){
                return (new Function('return '+text))()
            }
        })(),
        bind:function(fn,context){
            //就是用来改变this关键字
            if(Function.prototype.bind){
                return fn.bind(context)
            }else{
                return function(){
                    fn.apply(context,arguments)
                }
            }
        },
        each: (function () {
            if ([].forEach) {
                //如果数组中存在 forEach则
                //forEach是可以传递两个参数的一个回调 一个为回调的上下文
                return function (list) {
                    [].forEach.call(list, arguments[1], arguments[2])
                }
            }
            return function (list, callback) {
                for (var i = 0; i < list.length; i++) {
                    callback.call(arguments[2], list[i], i, list)
                }
            }
        })(),
        isType: function (type) {
            return function (obj) {
                return Object.prototype.toString.call(obj) == '[object ' + type + ']';
            }
        },
        //动态创建方法
        init: function () {
            util.each(['Array', 'Object', 'Function', 'String'], function (item) {
                //现在util.isArray...就是一个方法了 方法的内容是 function(obj){ return Object.prototype.toString.call(obj) == '[Object ' + type+']';}
                util['is' + item] = util.isType(item)
            })
        },
        forIn: function (obj, callback) {
            if (!util.isObject(obj))return;
            for (var key in obj) {
                if (!obj.hasOwnProperty(key))continue;
                callback.call(null, key, obj[key])
            }
        },
        traverse: function (obj) {
            //可以传随意参数
            if (util.isArray(obj)) {
                //第一个参数 改变的是里面所调用方法的指向
                return util.each.apply(null, arguments);
            }
            if(util.isObject(obj)){
                return util.forIn.apply(null,arguments);
            }
        },
        getXhR:(function(){
            var list = [function () {
                return new XMLHttpRequest();
            }, function () {
                return new ActiveXObject('Microsoft.XMLHTTP');
            }, function () {
                return new ActiveXObject('MsXML2.XMLHTTP');
            }, function () {
                return new ActiveXObject('MsXML3.XMLHTTP');
            }];
            for(var i=0;i<list.length;){
                try{
                    return list[i]
                }catch(err){
                    continue;
                }
            }
        })(),
        hasQuestionMark:function(str,data){
            var reg=/\?/igm;
            var temp='';
            if(reg.test(str)){
                //有有问号
                temp='&';
            }else{
                //没有问号
                temp='?';
            }
            //将拼接好的url返回
            return str+temp+data;
        }
    }
    //init执行了才会动态创建那些方法
    util.init();
    //链式写法
    var Promise=function(){
        this.onSuccess=this.onerror=new Function;//两个都是一个空函数
        this.isPromis=true;
    }
    Promise.prototype.success=function(fn){
        if(util.isFunction(fn)){
            this.onsuccess=fn;
        }
    }
    Promise.prototype.error=function(fn){
        if(util.isFunction(fn)){
            this.onerror=fn;
        }
    }
    var Deferred = function () {
        this.promise = new Promise();
        this.status = 'uninit';
    };
    Deferred.prototype.done = function (func) {
        this.status = 'done';
        this.promise.success(func);
        return this;
    };
    Deferred.prototype.fail = function (func) {
        this.status = 'fail';
        this.promise.error(func);
        return this;
    };
    util.each(['get', 'post', 'getScript'], function (item) {
        $http[item] = function (url, data, callback, datatype) {
            if (item == 'getScript') {
                item = 'get';
                var __callback = callback;
                callback = function (data) {
                    (new Function(data))();
                    __callback(data)
                }
            }
            return $http({
                type: item,
                url: url,
                data: data,
                success: callback,
                dataType: datatype
            });
        }
    })
})()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值