Ajax 整体结构

jQuery.Ajax做了那些事?

我们知道AJAX的底层实现其实是很简单的.抛开IE不说,标准的w3c直接提供了XMLHttpRequest方法

我们主要站在设计的角度理解,如何设计出低耦合高内聚的代码


jQuery对Ajax的处理主要体现在对浏览器兼容,数据的处理及过滤,各种事件的封装上


主要有以下几部分扩展:


提供快捷接口


提供底层接口


提供数据序列化


提供全局Ajax事件处理


具体使用请看API,这里不再重复


 




分析下面一个demo


给document绑定ajaxStart,ajaxComplete回调事件


trigger绑定一个点击事件,发送ajax请求


点击trigger出发点之后,发送一个ajax请求,并且通过complete,done,ajaxStart, ajaxComplete返回状态回调


复制代码
//全局事件触发
$(document).ajaxStart(function() {
    console.log(arguments)
}).ajaxComplete(function() {
    $(".log").text("Triggered ajaxComplete handler.");
});


$(".trigger").click(function() {
    //发送ajax请求
    //
    $.ajax({
        url: "php.html",
        context: document.body,
        complete: function() {
            console.log(this)
        }
    }).done(function() {
        console.log(this)
    });
});
复制代码


这里实现比较特别的地方


针对ajax提供2种回调方式,内部的complete回调与外部的done回调


全局document上都能捕获到ajax的每一步的回调通知


换句话说,针对ajax的请求,每一步的状态,成功或者失败,我们有3种方式可以获取,但是每一种还是有各自的区别


1 ajax的参数回调


2 基于deferred方式的done回调


3 全局的的自定义事件的回调


 




从设计的层面上来考下,这种事件组合的方式是如何实现?有什么优势?


设计一:


tAjax({
    url: "php.html",
    complete: function(data) {
        console.log(data)
    }
})


如果要实现这种接口调用


那么我们就需要封装下代码,把回调通过实参传递


复制代码
var tAjax = function(config) {
    var url      = config.url;
    var complete = config.complete; 
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    xhr.open('post', url);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                complete(xhr.responseText);
            }
        }
    }
    xhr.send();
}
复制代码


这样设计可以看做类似工厂模式的封装,好处不用多说,在工厂模式里面包含了对象的创建等必要的逻辑,客户端根据传参选择动态的实例化相对的处理


对于客户端来去除了具体的依赖,当然tAjax你也可以看作一个外观模式提供的接口,其实就是隐藏了具体的复杂逻辑,提供一个简单的接口,从而降低耦合


 




设计二:


复制代码
tAjax({
    url: "php.html",
    complete: function(data) {
        console.log(data)
    }
}).done(function(data){
    console.log(data)
})
复制代码


在之前加入了一个done链式处理,当然这里done,其实是deferred的一个成功处理通知,如果之前没有接触,大家去了解一下关于deferred的概念


我们知道jQuery实现了链式,实现的原理无法就是返回本身对象的引用


复制代码
var ajax = tAjax({
    url: "php.html",
    complete: function(data) {
        console.log(data)
    }
})

ajax.done(function(){
    
})
复制代码


以上是分离的情况下,如果要合并成一条链式处理,只要在上一个方法中返回this即可


所以我们改改


复制代码
var tAjax = function(config) {

    var doneFn;

    var url      = config.url;
    var complete = config.complete; 
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    xhr.open('post', url);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                doneFn(xhr.responseText);
                complete(xhr.responseText);
            }
        }
    }

    xhr.send(xhr.responseText);

    return {
        /**
         * 返回一个done对象
         */
        done: function(ourfn) {
             doneFn = ourfn;
        }
    };
}
复制代码


我们返回了一个done对象,这里一样要是对象,因为链式的原因,我们看外部指定了内部的done,从而把外部函数给引用到内部的doneFn上 缓存起来


xhr.staturs 成功后一起执行


当然这种设计是有问题的,如果在done之后我在链式就肯定不行,因为对象的引用错了,那么jQuery是如何处理?


 




设计三


提供document对象的全局处理


复制代码
$(document).ajaxComplete(function() {
    console.log('ajax请求成功')
});


tAjax({
    url: "php.html",
    complete: function(data) {
         console.log(data)
    }
}).done(function(data){
    console.log(data)
})
复制代码


这里的问题就是把ajax内部的事件,返回给全局捕获了,有点类似css3的全局动画事件


这里的设计其实最简单了因为本身之间没有什么耦合,就是发送一个事件给document即可


jQuery利用了trigger自定义事件触发的


globalEventContext.trigger("ajaxComplete", [jqXHR, s]);


具体每一种实现在后面的都会提到,在这里需要大家有个整体的印象,


 




总结:


通过读阅jQuery.ajax这段api我们可以看到jQuery对ajax的处理做的相当的全面


首先我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。


通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。


ajax引入了deferred方案,callback方案就是回调函数解决方案,从而处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口


伴随Ajax请求会触发若干事件,我们可以订阅这些事件并在其中处理我们的逻辑。


在jQuery中有两种Ajax事件:局部事件和全局事件。


局部事件(回调函数),在$.ajax()方法的options参数中声明,可以用来设置请求数据和获取、处理响应数据。


全局事件,每次Ajax请求都会触发,它会向DOM中的所有元素广播,你只需为DOM中任意元素bind好全局事件即会触发(若绑定多次,则会依次触发为事件注册的回调函数


除此之外,还提供了一系列的简化接口,比如.load ,还有直接对数据对象序列化的能力,对跨域的处理,contentType的修复等等


Ajax基础  使用Ajax发送异步请求  在请求和响应中使用XML  使用JSON进行数据传输 DOM基础  DOM是”Document Object Model”(文档对象模型)的首字母缩写。当创建了一个网页并把它加载到Web浏览器中时,就会在幕后创建一个文档对象模型  DOM表示被加载到浏览器窗口里的当前页面:浏览器向我们提供了当前页面的模型,而我们可以通过JavaScript访问这个模型  DOM把一份文档表示为一棵树  如下的HTML页面:  浏览器加载该页面并将之转换为树形结构:  DOM树中的一切是以最外层的HTML包含元素,即html元素开始的。使用树的比喻,这叫做根元素(root element)  从根流出的线表示不同标记部分之间的关系。head和body元素是html根元素的孩子(child);title是head的孩子,而文本 “Trees, trees, everywhere”是title的孩子;相对的,head是title的父亲(parent),title是文本 “Trees, trees, everywhere” 的父亲。处在同一层次的且互不包含的两个分支(如head和body)之间称为兄弟(sibling)关系。整个树就这样组织下去,直到浏览器获得与上图类似的结构  通常把这样的树结构成为一棵节点树 节点 (node)  DOM文档是由节点构成的集合,此时的节点是文档树上的树枝或者树叶  DOM中节点的类型:  元素节点(element node),诸如<head>、<p>、<div>等。元素节点可以包含其它的元素,唯一没有被包含在其它元素里的元素是<html>,它是根元素  属性节点(attribute node),元素或多或少地有一些属性,属性可以对元素做出一些具体的描述。因为属性总是被放到起始标签里,所以属性节点总是被包含在元素节点中  文本节点(text node),<h1>元素中包含着文本节点“Trees, trees, everywhere” 基本DOM方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值