Ajax通用代码封装

概要

ajax通用封装代码的分析
- ajax实现
- ajax请求的缓存问题
- 异步编程模型
- 页面历史记录问题

编写ajax程序的基本过程:
  1. 创建XMLHttpRequest对象
  2. open, 设置各类属性, method,async, url, url param data
  3. send, post data
  4. success, error ,alwarys callback
  5. timeout callback

调用示例,获取用户列表

ajax().get('/users').success(function(data){
    console.log(data);
});

通用ajax请求程序写法:

ajax(options)
    .before(callback(xhr))
    .header(name,value)
    .headers({headers})
    .get|post|other(url, [data], [contextType])
    .success(callback(returnData,xhr), [jsonForceValidate=false])
    .error(callback(statusCode, responseText, xhr))
    .always(callback(statusCode, responseText, xhr))
    .timeout(timeout,[callback(xhr)])

演示ajax请求的实现

演示ajax请求的实现:
Window.ajax = function (options){
    var defaultOptions = {
        async: true
    };

    options = extend(defaultOptions, options);

    //核心功能
    var _obj = {
        xhr: createXhr(),
        successCallbacks:[],
        errorCallbacks:[],
        alwaysCallback:[],
        options:options
    };

    //前置处理方法
    _obj.before = function(callback){
        typeof(callback) === 'function' && callback(_obj.xhr);
        return _obj;//为了支持链式操作,将原对象返回
    };

    //设置请求头
    //header方法在get|post之前执行
    _obj.header = function (name,value){
        _obj.xhr.setRequestHeader(name, value);
        return _obj;
    };

    //设置多个请求头
    _obj.headers = function(headers){
        if(object.prototype.toString.call(headers) === '[object Object'){
            for(var name in headers){
                _obj.xhr.setRequestHeader(name,headers[name]);
            }
        }
        return _obj;
    };

    //成功的回调
    _obj.success = function(callback, jsonForceValidate){
        _obj.jsonForceValidate = jsonForceValidate;

        if(typeof(callback) === 'function'){
            _obj.successCallbacks.push(callback);
        }
        return _obj;
    };

    //失败error的回调
    _obj.error = function(callback, jsonForceValidate){
        _obj.jsonForceValidate = jsonForceValidate;

        if(typeof(callback) === 'function'){
            _obj.errorCallbacks.push(callback);
        }
        return _obj;
    };

    //超时的回调
    _obj.timeout = function(timeout, callback){
        _obj.xhr.timeout = timeout;

        if(typeof(callback) === 'function'){
            _obj.xhr.ontimeout= function(){
                callback(_obj.xhr);
            }
        }
        return _obj;
    };

    //get method发起ajax请求

    // doAjax的操作
    function doAjax(_obj,method, url, data, contentType){
        var xhr = _obj.xhr;

        data = encodeData(data,contentType);

        if('get' === method){
            url += (url.indexof('?') == -1 ? '?' : '&') + data;
        }

        //绑定事件处理器
        bindEventHandler();

        //open 
        xhr.open(method, url, _obj.options.async);

        //send
        if('post' === method && data){
            xhr.setRequestHeader('content-Type', _obj.postContentType);
            xhr.send(data);
        }else{
            xhr.send();

        }
    };

    function encodeData(data, contentType){
        if(object.prototype.toString.call(data) === '[object Object]'){
            //json格式的处理
            if('json' === contentType.toLowerCase()
                && typeof(JSON) === 'object'
                && typeof(JSON.stringify)=== 'function'){

                _obj.postContentType = 'application/json';
                return JSON.stringify(data);
            } else{
                //其他情况用urlencode处理
                _obj.postContentType = 'application/x-www-form-urlencoded';
                return encodeParam(data);
            }
        }
    };


    function bindEventHandler(){

    };

    function extend(obj1,obj2){
        if(Object.prototype.toString.call(obj1) === '[object Object'
            && Object.prototype.toString.call(obj2) === '[object Object'){
            for (var pname in obj2){
                obj1[pname] = obj2[pname];
            }
        }
        return obj1;
    };
}

异步编程方法

异步编程方法
  1. 异步编程容易犯的错误:搞不清楚回调callback
  2. 多次请求仅仅允许最后一次有效
  3. 多个异步请求依次执行
  4. 多个异步请求同时执行

answer:

2.解决方法:请求放在全局变量中,第二次请求到来时,将第一次的全局变量abort(),后面的开始

3.

ajax().get('/req1', para).success(function(data){
    ajax.get('/req2', data).success(function(data2){
        ajax().get('/req3', data2).success(function(data3){
            //biz use data3
        });
    });
});
  1. 并行处理,通过异步计数器完成

页面历史记录功能

页面历史记录功能

(点击浏览器“后退”可以重现数据)
实现此功能的要点:点击后退按钮 需要使url的地址改变,且要保证页面整体不可以刷新
技术:浏览器地址的锚点变化,可以实现url不刷新改变

需要添加window.onload

第二种实现方法:
html5中添加了一个方法是history.pushState可以实现url的无刷新变化

    function beforeLoad(e){
        e && console.log(e.state);
        var search = window.location.search;
        if(search){
            search = search.substr(search.lastIndexOf('=') + 1);

        }
        loadData(search);
        btnState(search);
    }

    window.onload = window.onpopstate = beforeLoad;
    function hit(keyword){
        history.pushState({k:keyword}, 'new title', '/cache.html?keyword=' + keyword);
        beforeLoad();
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值