前端必备HTTP技能之Ajax技术详解

Ajax(Asynchronous JavaScript and XML)是一系列web开发技术的集合,使用很多的web技术在客户端开发异步web应用。利用Ajax,web应用可以异步的发送数据获取数据,而不干扰现有页面的显示和行为。通过解耦数据接口层和展现层,Ajax允许web页面或者其他扩展的web应用动态的改变数据而不用重新加载整个页面。实现通常选择JSON代替XML,因为更接近JavaScript。

Ajax不是一种技术,是一组技术。HTML和CSS用来组合标记和样式信息。用户可以利用js访问DOM对象负责动态展示。js和XMLHttpRequest对象提供一种浏览器和服务端异步互换数据的方法从而避免整个页面加载。

历史

在90年代中期,许多web站点完全基于html页面。每个用户行为都需要从服务端重新加载页面。这个过程很不方便,影响用户体验:所有的页面内容消失,然后又出现。每次因为小部分改动需要浏览器重新加载页面,所有内容都必须重新获取,甚至只有很少的信息改变。这会额外增加服务端负载,浪费带宽,影响性能。

在1996年,IE引入了iframe标签来异步加载获取内容。

在1998年,微软的邮件组团队利用客户端脚本实现了第一个XMLHTTP组件。

在1999年,微软在IE的默认页面使用iframe技术动态更新新闻故事和股票行情,并且在IE5中创建了XMLHTTP ActiveX组件,这个技术随后被Mozilla,Safari,Opera以及其他浏览器采用,作为XMLHttpRequest js对象。微软在IE7中采用了原生的XMLHttpRequest模块。IE仍然支持ActiveX版本,但是在Edge中不支持了。这种技术的使用在当时相当不明朗直到出现在大规模线上应用中,比如Outlook Web App (2000)和Oddpost

谷歌在Gmail(2004)和Google Maps(2005)中广发部署了符合标准的跨浏览器Ajax。在2004年10月Kayak.com的公测版本是首次大规模电子商务网站使用了他们当时称为"the xml htpp thing"的技术。

Jesse James Garrett在2005年2月18号发表的一篇题为"Ajax: A New Approach to Web Applications"的论文中,基于Google 页面中使用的技术,公开阐明了"Ajax"这个术语。

在2006年4月5号,W3C发表了第一个关于XMLHttpRequest对象的草案,尝试建立一个官方的Web标准。关于XMLHttpRequest对象最新的草案是在2014年1月30号发布的。

技术集

Ajax术语已经变成了web应用用来与服务端在幕后交流不打断页面当前状态而使用的一组技术的代表。在Jesse James Garrett的论文里创造的Ajax术语包括以下技术:

  • 展现层的HTML(或者XHTML)和CSS
  • 动态显示和与数据交互的DOM对象
  • 为了交换数据的JOSN或者XML,为了操纵数据的XSLT
  • 为了异步通信的XMLHttpRequest对象
  • 把这些技术整合起来的JavaScript

从那以后,Ajax应用使用的技术已经有了很大的发展,包括Ajax术语的定义。数据交换不再需要XML,操纵数据也不再需要XSLT了。JOSN经常被使用作为数据交换的一种格式,尽管其他的格式例如预定义的HTML或者纯文本仍然可以使用。

Asynchronous HTML and HTTP(AHAH)使用XMLHttpRequest对象获取(X)HTML片段,然后插入到Web页面中。

传统Web应用模型与使用Ajax的Web应用模型对比
传统Web应用模型与使用Ajax的Web应用模型对比

弊端

  • 如果用户浏览器不支持JavaScript或者XMLHttpRequest,或者禁用这种功能,则不能正常使用依赖Ajax的页面。简单设备(例如智能手机,pad)可能不支持需要的这些技术。让用户使用这种功能的唯一方法是回退到没有JavaScript方法。可以同通过确保链接表单正确解析而不是仅仅依赖Ajax来实现相关功能。
  • 同样的,一些使用Ajax的Web应用对屏幕阅读技术不友好,例如JAWSWAI-ARIA标准提供了一种方法在这种情况下提供提示。
  • 屏幕阅读器可以使用Ajax,但是也可能不能正确的读取动态产生的内容。
  • 同源策略阻止了一些Ajax技术跨域使用,尽管W3C有关于XMLHttpRequest对象的草案允许这个功能。通过使用一个特别的跨域通道例如页面中的iframe或者使用JSONP可以跨过这种安全限制。
  • 异步的回调编程可能导致负责的代码难以维护,调试和测试。
  • 因为Ajax的异步特性,客户端发送接收到每块数据都发生在专门为改事件建立的连接上。这就为每个行为增加一种需要,那就是客户端必须轮询服务端,而不是监听,这就会导致额外开销。这种开销会导致Ajax应用有更高的延迟相比于利用websocket技术获取数据。
  • 在非HTML5浏览器中,使用Ajax请求创建的动态页面不能自动的注册到浏览器的历史记录中,所以在点击浏览器"回退"按钮时,浏览器不会回到Ajax发生之前的状态,但是会回退到上次访问的页面。这种在页面之间导航而不是在页面状态之间导航的行为可能不是想要的,但是如果需要追踪页面状态,那么对于非HTML5的浏览器一个变通的方案就是使用非透明的iframe触发浏览器历史记录的改变。另一个变通方法就是利用Ajax技术更改URL的片段标识符(URL中在"#"之后的部分)。HTML5提供了一个扩展的API标准来操作浏览器历史记录。
  • 动态web页面更新导致很难记标签,返回应用的特性状态。这种问题的解决办法也是存在的,也是利用URL的片段标识符。HTML5提供了解决上面问题的方法。
  • 由于Ajax应用的特性,动态页面更新可能会打断用户交互,特别是当网络连接很慢或者不可能的时候。例如,编辑一个搜索框可能会触发一个服务端查询,但是用户可能不知道查询结束时会弹出一个框,如果此时网络很慢,弹窗可能会在一个不恰当的时候弹出,当用户已经开始处理其他的事情时。
  • 除了Google,大多数网络爬虫不能执行js代码,所以为了被搜索引擎收录,Web应用必须为那些通过Ajax获取内容的页面提供一个备选页面。

例子

下面就是一个简单的使用GET方法进行Ajax请求的例子
get-ajax-data.js:

var xhr = new XMLHttpRequest();
xhr.open('get', 'send-ajax-data.php');
xhr.onreadystatechange = function () {
    var DONE = 4;
    var OK = 200;
    if (xhr.readyState === DONE) {
        if (xhr.status === OK) {
            alert(xhr.responseText);
        } else {
            alert('Error: ' + xhr.status);
        }
    }
};
xhr.send(null);

send-ajax-data.php:

header('Content-Type: text/plain');
echo "This is the returned text.";
jQuery示例

使用流行的jQuery库,完成上例中相同的事情

$.get('send-ajax-data.php')
    .done(function(data) {
        alert(data);
    })
    .fail(function(data) {
        alert('Error: ' + data);
    });

做好前端开发必须对HTTP的相关知识有所了解,所以我创建了一个专题前端必备HTTP技能专门收集前端相关的HTTP知识,欢迎关注,投稿。


PS:本文翻译自维基百科,原文地址https://en.wikipedia.org/wiki/Ajax_(programming)

推荐阅读更多精彩内容