深入浅出Ajax
原文(我的GitHub):https://github.com/liangfengbo/frontend-ability/issues/1
学习大纲
Ajax的工作原理
含义:
1. w3chool官网:Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
2. 我的理解:无须刷新页面即可从服务器取得数据的技术。
原理:
Ajax的工作原理相当于在用户和服务器之间加了—个中间层,使用户操作与服务器响应异步化。并不是所有的用户请求都提交给服务器,像—些数据验证和数据处理等都交给Ajax引擎自己来做, 只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。
核心XMLHttpRequest对象
Ajax技术的核心是XMLHttpRequest对象。
- IE5 XHR对象是通过MSXML库中的一个ActiveX对象实现的,所以要考虑做兼容。
- IE7+、Firefox、Opera、Chrome和Safari都支持原生的XHR对象
new ActiveXObject(versions);
new XMLHttpRequest();
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(未找到)等等) |
XMLHttpRequest进度事件
事件 | 描述 |
---|---|
loadstart | 在接收到响应数据的第一个字节时触发。 |
progress | 在接收响应期间持续不断地触发。 |
error | 在请求发生错误时触发。 |
abort | 在因为调用abort()方法而终止连接时触发。 |
load | 在接收到完整的响应数据时触发。 |
loadend | 在通信完成或者触发error、abort或load事件后触发。 |
封装ajax方法
/**
* 创建Ajax
* @param options
*/
function Ajax(options) {
// 新建一个对象,用途接受XHR对象
var xhr = null;
// 第一步创建XMLHttpRequest对象 || 同时兼任IE
// 首先检测原生XHR对象是否存在,如果存在则返回它的新实例
if (typeof XMLHttpRequest != "undefined") {
xhr = new XMLHttpRequest();
// 然后如果原生对象不存在,则检测ActiveX对象
} else if (typeof ActiveXObject != "undefined") {
// 如果存在,则创建他的对象,但这个对象需要一个传入参数,如下:
if (typeof arguments.callee.activeXString != 'string') {
// 对象版本
var versions = [
'Microsoft.XMLHTTP',
'Msxml2.XMLHTTP.7.0',
'Msxml2.XMLHTTP.6.0',
'Msxml2.XMLHTTP.5.0',
'Msxml2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML.XMLHTTP'
], i, len;
for (i = 0, len = versions.length; i < len; i++) {
try {
// 需要versions数组中的某个项,数组的7个项分别对应7个版本.
new ActiveXObject(versions[i]);
// arguments是javascript函数的内置对象,代表传入参数的集合,
// callee就代表对象本身即new createXHR
arguments.callee.activeXString = versions[i];
break;
} catch (e) {
// 跳过
}
}
}
// 直到循环创建成功为止,然后给自己添加一个属性叫activeXString
xhr = new ActiveXObject(arguments.callee.activeXString);
} else {
// 如果这两种对象都不存在,就抛出一个错误
throw new Error('No XHR object available');
}
/**
** options形参解析:
* data 发送的参数,格式为对象类型
* url 发送请求的url,服务器地址(api)
* async 否为异步请求,true为异步的,false为同步的
* method http连接的方式,包括POST和GET两种方式
*/
options = options || {};
options.success = options.success || function () {
};
options.fail = options.fail || function () {
};
var data = options.data,
url = options.url,
async = options.async === undefined ? true : options.async,
method = options.method.toUpperCase(),
dataArr = [];
// 遍历参数
for (var k in data) {
dataArr.push(k + '=' + data[k]);
}
// GET请求
if (method === 'GET') {
url = url + '?' + dataArr.join('&');
xhr.open(method, url.replace(/\?$/g, ''), async);
xhr.send();
}
// POST请求
if (method === 'POST') {
xhr.open(method, url, async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(dataArr.join('&'));
}
// 响应接收完毕后将触发load事件
xhr.onload = function () {
/**
* XHR对象的readyState属性
* 0:未初始化。尚未调用open()方法。
* 1:启动。已经调用open()方法,但尚未调用send()方法。
* 2:发送。已经调用send()方法,但尚未接收到响应。
* 3:接收。已经接收到部分响应数据。
* 4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
*/
if (xhr.readyState == 4) {
// 得到响应
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
// 处理成功数据
var res;
if (options.success && options.success instanceof Function) {
res = xhr.responseText;
if (typeof res === 'string') {
res = JSON.parse(res);
options.success.call(xhr, res);
}
}
} else {
// 处理错误数据
if (options.fail && options.fail instanceof Function) {
options.fail.call(xhr, res)
}
}
} else {
// 抛出检测XHR对象的readyState属性
console.log('XHR was readyState:', xhr.readyState);
}
}
}
options参数说明
参数 | 类型 | 描述 | 默认值 | 是否填 |
---|---|---|---|---|
url | string | 发送请求的url,服务器地址(api) | '' | 必填 |
method | string | http连接的方式,包括POST和GET两种方式 | true | 选填 |
async | boolean | 是否为异步请求,true为异步的,false为同步的 | true | 选填 |
data | json | 发送的参数,格式为对象(json)类型 | null | 选填 |
success | function | 请求成功回调函数 | function () | 必填 |
fail | function | 请求失败回调函数 | function () | 必填 |
示例:
Ajax({
url: 'http://localhost:3000/api/v1/article',
method: 'GET',
async: true,
success: function (res) {
console.log('successful', res);
},
fail: function (err) {
console.log('fail', err);
}
})
成功返回数据:
successful {code: 200, msg: "查询文章列表成功!", data: {…}}
Ajax优点
1.无刷新更新数据。
AJAX最大优点就是能在不刷新整个页面的前提下与服务器通信维护数据。这使得Web应用程序更为迅捷地响应用户交互,并避免了在网络上发送那些没有改变的信息,减少用户等待时间,带来非常好的用户体验。
2.异步与服务器通信。
AJAX使用异步方式与服务器通信,不需要打断用户的操作,具有更加迅速的响应能力。优化了Browser和Server之间的沟通,减少不必要的数据传输、时间及降低网络上数据流量。
3.前端和后端负载平衡。
AJAX可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,AJAX的原则是“按需取数据”,可以最大程度的减少冗余请求和响应对服务器造成的负担,提升站点性能。
4.基于标准被广泛支持。
AJAX基于标准化的并被广泛支持的技术,不需要下载浏览器插件或者小程序,但需要客户允许JavaScript在浏览器上执行。随着Ajax的成熟,一些简化Ajax使用方法的程序库也相继问世。同样,也出现了另一种辅助程序设计的技术,为那些不支持JavaScript的用户提供替代功能。
5.界面与应用分离。
Ajax使WEB中的界面与应用分离(也可以说是数据与呈现分离),有利于分工合作、减少非技术人员对页面的修改造成的WEB应用程序错误、提高效率、也更加适用于现在的发布系统。
Ajax缺点
1.AJAX干掉了Back和History功能,即对浏览器机制的破坏。
在动态更新页面的情况下,用户无法回到前一个页面状态,因为浏览器仅能记忆历史记录中的静态页面。一个被完整读入的页面与一个已经被动态修改过的页面之间的差别非常微妙;用户通常会希望单击后退按钮能够取消他们的前一次操作,但是在Ajax应用程序中,这将无法实现
2.AJAX的安全问题
JAX技术给用户带来很好的用户体验的同时也对IT企业带来了新的安全威胁,Ajax技术就如同对企业数据建立了一个直接通道。这使得开发者在不经意间会暴露比以前更多的数据和服务器逻辑。Ajax的逻辑可以对客户端的安全扫描技术隐藏起来,允许黑客从远端服务器上建立新的攻击。还有Ajax也难以避免一些已知的安全弱点,诸如跨站点脚步攻击、SQL注入攻击和基于Credentials的安全漏洞等等
3.对搜索引擎支持较弱。
对搜索引擎的支持比较弱。如果使用不当,AJAX会增大网络数据的流量,从而降低整个系统的性能。
4.破坏程序的异常处理机制。
至少从目前看来,像Ajax.dll,Ajaxpro.dll这些Ajax框架是会破坏程序的异常机制的。关于这个问题,曾在开发过程中遇到过,但是查了一下网上几乎没有相关的介绍。后来做了一次试验,分别采用Ajax和传统的form提交的模式来删除一条数据……给我们的调试带来了很大的困难
5.AJAX不能很好支持移动设备。
一些手持设备(如手机、PDA等)现在还不能很好的支持Ajax,比如说我们在手机的浏览器上打开采用Ajax技术的网站时,它目前是不支持的。
Ajax适用场景
- 表单驱动的交互
- 深层次的树的导航
- 快速的用户与用户间的交流响应
- 类似投票、yes/no等无关痛痒的场景
- 对数据进行过滤和操纵相关数据的场景
- 普通的文本输入提示和自动完成的场景
Ajax不适用场景
- 部分简单的表单
- 搜索
- 基本的导航
- 替换大量的文本
- 对呈现的操纵
Ajax常见面试题:
1、Ajax是什么?如何创建一个Ajax?
Ajax并不算是一种新的技术,全称是asychronous javascript and xml,可以说是已有技术的组合,主要用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新,早期的浏览器并不能原生支持ajax,可以使用隐藏帧(iframe)方式变相实现异步效果,后来的浏览器提供了对ajax的原生支持
使用ajax原生方式发送请求主要通过XMLHttpRequest(标准浏览器)、ActiveXObject(IE浏览器)对象实现异步通信效果
基本步骤:
var xhr =null;//创建对象
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open(“方式”,”地址”,”标志位”);//初始化请求
xhr.setRequestHeader(“”,””);//设置http头信息
xhr.onreadystatechange =function(){}//指定回调函数
xhr.send();//发送请求
js框架(jQuery/EXTJS等)提供的ajax API对原生的ajax进行了封装,熟悉了基础理论,再学习别的框架就会得心应手,好多都是换汤不换药的内容
2、同步和异步的区别?
同步:阻塞的
- 张三叫李四去吃饭,李四一直忙得不停,张三一直等着,直到李四忙完两个人一块去吃饭,浏览器向服务器请求数据,服务器比较忙,浏览器一直等着(页面白屏),直到服务器返回数据,浏览器才能显示页面
异步:非阻塞的
- 张三叫李四去吃饭,李四在忙,张三说了一声然后自己就去吃饭了,李四忙完后自己去吃,浏览器向服务器请求数据,服务器比较忙,浏览器可以自如的干原来的事情(显示页面),服务器返回数据的时候通知浏览器一声,浏览器把返回的数据再渲染到页面,局部更新
3、如何解决跨域问题?
理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域
出于安全考虑,服务器不允许ajax跨域获取数据,但是可以跨域获取文件内容,所以基于这一点,可以动态创建script标签,使用标签的src属性访问js文件的形式获取js脚本,并且这个js脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的主流解决方案
4、页面编码和被请求的资源编码如果不一致如何处理?
对于ajax请求传递的参数,如果是get请求方式,参数如果传递中文,在有些浏览器会乱码,不同的浏览器对参数编码的处理方式不同,所以对于get请求的参数需要使用encodeURIComponent函数对参数进行编码处理,后台开发语言都有相应的解码api。对于post请求不需要进行编码
5、简述ajax的过程。
-
创建XMLHttpRequest对象,也就是创建一个异步调用对象
-
创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
-
设置响应HTTP请求状态变化的函数
-
发送HTTP请求
-
获取异步调用返回的数据
-
使用JavaScript和DOM实现局部刷新
6、阐述一下异步加载JS。
-
异步加载的方案: 动态插入 script 标签
-
通过 ajax 去获取 js 代码,然后通过 eval 执行
-
script 标签上添加 defer 或者 async 属性
-
创建并插入 iframe,让它异步执行 js
7、请解释一下 JavaScript的同源策略。‘’
同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。所谓同源指的是:协议,域名,端口相同,同源策略是一种安全协议,指一段脚本只能读取来自同一来源的窗口和文档的属性。
8、GET和POST的区别,何时使用POST?
GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符,有的浏览器是8000个字符
POST:一般用于修改服务器上的资源,对所发送的信息没有限制
在以下情况中,请使用 POST 请求:
-
无法使用缓存文件(更新服务器上的文件或数据库)
-
向服务器发送大量数据(POST 没有数据量限制)
-
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
9、ajax是什么?ajax的交互模型?同步和异步的区别?如何解决跨域问题?
-
通过异步模式,提升了用户体验
-
优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
-
Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
10、 Ajax的最大的特点是什么。
Ajax可以实现异步通信效果,实现页面局部刷新,带来更好的用户体验;按需获取数据,节约带宽资源;
11、ajax的缺点
1、ajax不支持浏览器back按钮。
2、安全问题 AJAX暴露了与服务器交互的细节。
3、对搜索引擎的支持比较弱。
4、破坏了程序的异常机制。
12、ajax请求的时候get和post方式的区别
get一般用来进行查询操作,url地址有长度限制,请求的参数都暴露在url地址当中,如果传递中文参数,需要自己进行编码操作,安全性较低。
post请求方式主要用来提交数据,没有数据长度的限制,提交的数据内容存在于http请求体中,数据不会暴漏在url地址中。
13、解释jsonp的原理,以及为什么不是真正的ajax
Jsonp并不是一种数据格式9,而json是一种数据格式,jsonp是用来解决跨域获取数据的一种解决方案,具体是通过动态创建script标签,然后通过标签的src属性获取js文件中的js脚本,该脚本的内容是一个函数调用,参数就是服务器返回的数据,为了处理这些返回的数据,需要事先在页面定义好回调函数,本质上使用的并不是ajax技术
14、什么是Ajax和JSON,它们的优缺点。
Ajax是全称是asynchronous JavaScript andXML,即异步JavaScript和xml,用于在Web页面中实现异步数据交互,实现页面局部刷新。
优点:可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量,避免用户不断刷新或者跳转页面,提高用户体验
缺点:对搜索引擎不友好;要实现ajax下的前后退功能成本较大;可能造成请求数的增加跨域问题限制;
JSON是一种轻量级的数据交换格式,ECMA的一个子集
优点:轻量级、易于人的阅读和编写,便于机器(JavaScript)解析,支持复合数据类型(数组、对象、字符串、数字)
15、http常见的状态码有那些?分别代表是什么意思?
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
16、一个页面从输入 URL到页面加载显示完成,这个过程中都发生了什么?
分为4个步骤:
-
当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器上启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址。
-
浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
-
一旦 TCP/IP 连接建立,浏览器会通过该连接向远程服务器发送 HTTP 的 GET 请求。远程服务器找到资源并使用 HTTP 响应返回该资源,值为 200 的 HTTP 响应状态表示一个正确的响应。
-
此时,Web 服务器提供资源服务,客户端开始下载资源。
17、ajax请求的时候get和post方式的区别
get一般用来进行查询操作,url地址有长度限制,请求的参数都暴露在url地址当中,如果传递中文参数,需要自己进行编码操作,安全性较低。
post请求方式主要用来提交数据,没有数据长度的限制,提交的数据内容存在于http请求体中,数据不会暴漏在url地址中。
18、ajax请求时,如何解释json数据
使用eval() 或者JSON.parse() 鉴于安全性考虑,推荐使用JSON.parse()更靠谱,对数据的安全性更好。
参考文档
JavaScript高级程序设计第三版
AJAX工作原理及其优缺点
Ajax原理以及优缺点
Ajax的工作原理
Ajax系列面试题总结01