阅读 1293

《看完就懂系列》Ajax是不是凭一己之力造就了整个前端的生态圈?

这是大冰块2021年第6篇原创文章,和大冰块一起在前端领域努力吧!!!💪


写在前面

前几天,有小伙伴面试的时候被面试官问:谈谈Ajax的原理~ 他说回答得不太好。我想,Ajax有什么原理?不就是发请求拿数据渲染页面吗?抱着怀疑即是寻求真理的想法,我重新梳理了一遍Ajax的发展过程。发现Ajax简直是凭一己之力造就了整个前端生态圈啊,如果没有Ajax技术,今天的我可能就是一个java程序员了,然后写着jsp的页面~

这么说吧:没有Ajax,就没有前端处理渲染数据的可能,没有局部刷新,没有动态渲染,没有实时交互,没有前后端分离,后端工作量更大,...今天几乎所有的网站都离不开它~

什么是Ajax

维基百科介绍了Ajax的发展史:

20世纪90年代,几乎所有的网站都由HTML页面实现,服务器处理每一个用户请求都需要重新加载网页。这样的处理方式效率不高。用户的体验是所有页面都会消失,再重新加载,即使只是一部分页面元素改变也要重新加载整个页面,不仅要刷新改变的部分,连没有变化的部分也要刷新。这会加重服务器的负担。

这可以用异步加载来解决。1995年,JAVA语言的第一版发布,随之发布的的Java applets(JAVA小程序)首次实现了异步加载。浏览器通过运行嵌入网页中的Java applets与服务器交换数据,不必刷新网页。1996年,Internet Explorer将iframe元素加入到HTML,支持局部刷新网页。

1998年前后,Outlook Web Access小组写成了允许客户端脚本发送HTTP请求XMLHTTP的第一个组件。该组件原属于微软Exchange Server,并且迅速地成为了Internet Explorer 4.0[2]的一部分。部分观察家认为,Outlook Web Access是第一个应用了Ajax技术的成功的商业应用程序,并成为包括Oddpost的网络邮件产品在内的许多产品的领头羊。

但是,2005年初,许多事件使得Ajax被大众所接受。Google在它著名的交互应用程序中使用了异步通讯,如Google讨论组、Google地图、Google搜索建议、Gmail等。Ajax这个词由《Ajax: A New Approach to Web Applications》一文所创,该文的迅速流传提高了人们使用该项技术的意识。另外,对Mozilla/Gecko的支持使得该技术走向成熟,变得更为简单易用。

Ajax包含

基于XHTMLCSS标准的表示; 使用DOM(Document Object Model)进行动态显示和交互; 使用XMLHttpRequest与服务器进行异步通信; 使用JavaScript绑定数据。

Ajax的原理

Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化,也就是javascript可以同时向服务器发起请求和接收响应,这个过程不阻塞用户操作以及页面渲染。

当然,不是所有的用户请求都会提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。当从服务器获得数据后,就用javascript来操作DOM更新页面

这其中最关键的一步就是从服务器获得请求数据。要清楚这个过程和原理,我们必须对 XMLHttpRequest有所了解。

异步请求

异步的意思就是:做一件事的同时,可以去做另外一件事。

同步的意思就是:做一件事没有完成,就不能去做下一件事。

异步请求是Ajax的精髓所在,而XMLHttpRequest就是Ajax的核心机制,它是在IE5中首先引入的,是一种支持异步请求的技术,XMLHttpRequestXMLHTTP组件的一个对象。下面来说一下这个对象的方法与属性:

XMLHttpRequest 对象方法

方 法描 述
abort()停止当前请求
getAllResponseHeaders()把HTTP请求的所有响应首部作为键/值对返回
getResponseHeader("header")返回指定首部的串值
open("method","URL",[asyncFlag],["userName"],["password"])建立对服务器的调用。method参数可以是GET、POST或PUT。url参数可以是相对URL或绝对URL。这个方法还包括3个可选的参数,是否异步,用户名,密码
send(content)向服务器发送请求
setRequestHeader("header", "value")把指定首部设置为所提供的值。在设置任何首部之前必须先调用open()。设置header并和请求一起发送 ('post'方法一定要 )

XMLHttpRequest 对象属性

属 性描 述
onreadystatechange状态改变的事件触发器,每个状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数
readyState请求的状态。有5个可取值:0 = 未初始化,1 = 正在加载,2 = 已加载,3 = 交互中,4 = 完成
responseText服务器的响应,返回数据的文本。
responseXML服务器的响应,返回数据的兼容DOM的XML文档对象 ,这个对象可以解析为一个DOM对象。
responseBody服务器返回的主题(非文本格式)
responseStream服务器返回的数据流
status服务器的HTTP状态码(如:404 = "文件末找到" 、200 ="成功" ,等等)
statusText服务器返回的状态文本信息 ,HTTP状态码的相应文本(OK或Not Found(未找到)等等)

Ajax的使用

在现在前端开发过程中,Ajax都已经被框架或者组件经过了二次封装,我们直接拿来使用即可,不必再重复造轮子。不过熟悉封装的基础原理还是很有必要的,了解原理才能在debug的时候快速准确找到问题所在~

所以下面大冰块来详细的讲解一下Ajax的封装过程~

一,创建 Ajax 对象

// XmlHttpRequest对象在不同浏览器中不同的创建方法,以下是跨浏览器的通用方法:
var xmlHttp
if (typeof XMLHttpRequest != "undefined") {
    xmlHttp = new XMLHttpRequest()
} else if (window.ActiveXObject) {
    var aVersions = ["Msxml2.XMLHttp.5.0", "Msxml2.XMLHttp.4.0", "Msxml2.XMLHttp.3.0", "Msxml2.XMLHttp", "Microsoft.XMLHttp"];
    for (var i = 0; i < aVersions.length; i++) {
        try {
            xmlHttp = new ActiveXObject(aVersions[i])
            break
        } catch (e) {}
    }
}
复制代码

二,调用 opensend

// 传入请求方式,请求地址和是否异步的布尔值
xhr.open('GET', './getNews', true)
// 使用GET请求时候不需要设置如下编码:
// xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
xhr.send();
复制代码

三,监听 onreadystatechange 事件

xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        // 响应数据 转成 json 格式,好让我们使用。 
     console.log(JSON.parse(xhr.responseText)) 
    }
}
复制代码

根据上面的说明,我们完全可以自己封装一个Ajax来使用了,下面我们尝试着封装一下~

四,自己封装一个Ajax

function myAjax (options){
    this.method = options.method
    this.url = options.url
    this.data = options.data || ''
    this.flag = options.flag || true
    this.callback = options.callback
    var self = this
    var xmlHttp
    if (typeof XMLHttpRequest != "undefined") {
        xmlHttp = new XMLHttpRequest()
    } else if (window.ActiveXObject) {
        var aVersions = ["Msxml2.XMLHttp.5.0", "Msxml2.XMLHttp.4.0", "Msxml2.XMLHttp.3.0", "Msxml2.XMLHttp", "Microsoft.XMLHttp"];
        for (var i = 0; i < aVersions.length; i++) {
            try {
                xmlHttp = new ActiveXObject(aVersions[i])
                break
            } catch (e) {}
        }
    }
    if(this.method == 'GET' || this.method == 'get'){
        xmlHttp.open('GET', this.url + "?" + this.data, this.flag)
        xmlHttp.send()
    }else{
        xmlHttp.open('POST', this.url, this.flag)
        xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        xmlHttp.send(this.data)
    }
    xmlHttp.onreadystatechange = function(){
        if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
            if(self.method == 'GET' || self.method == 'get'){
                self.callback(JSON.parse(xmlHttp.responseText))
            }else{
                self.callback(xmlHttp.responseText)
            }
        }
    }
}
复制代码

Ajax优缺点总结

  1. 不刷新页面只更新数据 在不刷新整个页面的前提下与服务器交互数据。这使得Web应用程序更为迅捷地响应用户交互,并避免了在网络上发送那些没有改变的信息,减少用户等待时间,带来非常好的用户体验。

  2. 异步与服务器通信 Ajax使用异步方式与服务器通信,不需要打断用户的操作,具有更加迅速的响应能力。优化了浏览器和服务器之间的沟通,减少不必要的数据传输、时间及降低网络上数据流量。

  3. 前端和后端负载平衡。 Ajax可以把以前一些服务器负担的工作移交给客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。Ajax的原则是“按需取数据”,可以最大程度的减少冗余请求和响应对服务器造成的负担,提升站点性能。

  4. 引发的安全问题。 Ajax技术给用户带来很好的用户体验的同时也对IT企业带来了新的安全威胁,Ajax技术就如同对企业数据建立了一个直接通道。这使得开发者在不经意间会暴露比以前更多的数据和服务器逻辑。Ajax的逻辑可以对客户端的安全扫描技术隐藏起来,允许黑客从远端服务器上建立新的攻击。还有Ajax也难以避免一些已知的安全弱点,诸如跨站点脚步攻击、SQL注入攻击和基于Credentials的安全漏洞等等。

  5. 架构设计问题

    将表现层、业务逻辑、及数据层都放在服务器,浏览器仅有用户接口引擎(User Interface engine);此法又称为瘦客户端(thin client)架构,或中心服务器(server-centric)架构。这么做会更符合终端用户的要求,但是JavaScript的设计以及执行性能可能不足以处理复杂的业务逻辑。

    表现层、逻辑层都可以放在客户端进行处理,因为所有的程序以JavaScript执行在客户端,只有需要数据时才向服务器要求服务,此法又称为胖客户端(fat client)架构。服务器在此架构下通常仅用于提供及储存数据。这么做在开发应用程序时相对容易,但是表现层都是固定的模板样式,改动的成本较高。

  6. 浏览器的兼容性

    Ajax在本质上是一个浏览器端的技术,首先面临无可避免的第一个问题即是浏览器的兼容性问题。各家浏览器对于JavaScript/DOM/CSS的支持总有部分不太相同或是有Bug,甚至同一浏览器的各个版本间对于JavaScript/DOM/CSS的支持也有可能部分不一样。这导致程序员在写Ajax应用时花大部分的时间在调试浏览器的兼容性而非在应用程序本身。因此,目前大部分的Ajax链接库或开发框架大多以js链接库的形式存在,以定义更高阶的JavaScript APIJavaScript对象(模板)、或者JavaScript Widgets来解决此问题。如prototype.js

    不过目前浏览器厂商也在按照web标准W3C标准等来改进浏览器,我相信有一天前端的开发时间不会再被兼容性所影响,而是花在钻研技术上。

经过对Ajax的重新梳理,我又发现了很多之前自己不熟悉的点,相当于重新学习了一遍Ajax。技术的发展与进步都离不开最基础的知识,虽然前端要学的的框架与知识越来越多,但最重要的还是最基础的JavaScript。关于Ajax虽然写出来的都蛮基础的,但和刚接触前端时的自己相比,还是感觉体会更深刻了(下次面试遇到还能愉快的吹一下~😜),希望你也有同样的感受。

写在后面

这是大冰块《看完就懂系列》的第5篇文章,《看完就懂系列》旨在把一些常见的概念或方法以通俗易懂的方式呈现出来。欢迎大家点击其他文章一起讨论学习:

原创不易,如有错误,欢迎指出。

如果有帮助到你,请给大冰块来个三连(点赞收藏评论),让我们一起在前端的路上进步吧~🤭