JavaScript学习笔记---Ajax入门(一)

通过上一篇文章,我们对Ajax有了大概的了解, 接下来再进一步剖析, 首先我们先理解好下面几个概念及其过程:

网页浏览过程分析

一个完整的HTTP请求过程,通常有下面7个步骤

1、建立TCP连接
2、Web浏览器向Web服务器发送请求命令
3、Web浏览器发送请求头信息
4、Web服务器- 应答
5、Web服务器- 发送应答头信息
6、Web服务器- 向浏览器发送数据
7、Web服务器- 关闭TCP连接

Ajax原理

理解同步和异步(基本都用异步请求).

  • 同步: 客户端发起请求–等待–>服务器端处理—等待–>响应–>页面载入 (请求错误时全部重新载入)。
  • 异步: 客户端发起请求—>服务器端处理—>响应—>页面载入(填写时,即时更新,部分返回)。

注: 其它详情请看前一篇博文

HTTP请求

一个HTTP请求一般由四部分组成

HTTP请求的方法或动作(一般是get或者post)
正在请求的URL
请求头(包含一些客户端环境信息,身份验证信息等)
请求体(请求正文,请求正文中可以包含客户端提交的查询字符串信息,表单信息等等)
http请求

HTTP响应

一个HTTP响应一般由三部分组成:

状态码(由数字组成,用来显示请求是成功还是失败)
响应头(响应头和请求头一样包含许多有用的信息,例如服务器类型,日期时间,内容类型和长度等)
响应体(也就是响应正文).
http响应

常见的HTTP请求方式

GET POST
用于信息获取/查询(如:浏览帖子) 用于修改服务器上的资源(如:用户注册)
安全性低(使用url传递参数所有人可见) 安全性一般(至少不可见)
容量低(2000个字符) 容量几乎无限

常见的HTTP状态码

状态码 描述 原因短语
200 请求成功.一般用于GET和POST方法 OK
301 资源移动.所请求资源移动到新的URL,浏览器自动跳转到新的URL Moved Permanently
304 未修改.所请求资源未修改读取缓存数据 Not Modified
400 请求语法错误,服务器无法理解 Bad Request
404 未找到资源,可以设置个性”404页面” Not Found
500 服务器内部错误 internal Server Error

编写Ajax

类比打电话理解Ajax编写步骤

打电话 ajax请求
1.打电话 1.创建Ajax对象
2.拨号 2.连接服务器
3.建立连接 3.发送请求
4.听 4.接受返回

1、创建Ajax对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createXmlHttp() { 
if (window.XmlHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = newXmlHttpRequest();
}
if (window.ActiveXObject) { // code for IE6, IE5
try {
xmlhttp = newActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
try {
xmlhttp = newActiveXObject("msxml2.XMLHTTP");
} catch (ex) {}
}
}
}

2、连接服务器

1
2
3
//open(发送请求方法”GET/POST” ,(请求地址”文件名”) ,是否异步传输)
//open(method,url,async); 例如:
request.open("GET","get.json",true);

注意
 千万不要把第三个参数指定为false,否则浏览器将停止响应,直到AJAX请求完成。如果这个请求耗时10秒,那么10秒内你会发现浏览器处于“假死”状态。

最后调用send()方法才真正发送请求。GET请求不需要参数,POST请求需要把body部分以字符串或者FormData对象传进去。

3、发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**send(string)
在使用GET方式请求时无需填写参数
在使用POST方式时参数代表着向服务器发送的数据
**/


//完整的GET请求
createXmlHttp();//创建Ajax对象
if (!xmlhttp) {
alert("创建xmlhttp对象异常!");
return false;
}
xmlhttp.open("GET",url,true);//连接服务器
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
document.getElementById("xxx").innerHTML = "数据正在加载...";
if (xmlhttp.status == 200) {
document.write(xmlhttp.responseText);
}
}
}
xmlhttp.send();//发送请求

//完整的POST发送请求
createXmlHttp();
if (!xmlhttp) {
alert("创建xmlhttp对象异常!");
return false;
}
xmlhttp.open("POST", url, true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
document.getElementById("xxx").innerHTML = "数据正在加载...";
if (xmlhttp.status == 200) {
document.write(xmlhttp.responseText);
}
}
}
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");//设置HTTP头信息.必须在open与send之间,否则出现异常.
xmlhttp.send("name=张三&sex=男");//发送给服务器的内容

4、接受返回(XMLHttpRequset取得响应)

属性
responseText 获得字符串形式的响应数据
responseXML 获得XML形式的响应数据
status和statusText 以数字和文本方式返回HTTP状态码
getAllResponseHeader() 获取所有的响应报头
getResponseheader() 查询响应中的某个字段的值

通过监听onreadystatechange事件,来判断请求的状态(readyState属性:响应返回所处状态).

状态码 状态 所处位置
0 未初始化 还没有调用open()方法
1 载入 已调用send()方法,正在发送请求
2 载入完成 send()方法完成,已经收到全部响应内容
3 解析 正在解析响应内容
4 完成 响应内容解析完成,可以在客户端调用了

使用函数简单的封装一个get请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 一个简单的异步get请求
* @param {String} url 请求地址,文件名
* @param {Function} fnSucc 请求成功时执行的函数,形参为为获取的字符串值.
* @param {Function} fnFaild 请求失败执行的函数,可选参数
*/

function get(url, fnSucc, fnFaild) {
//1.创建ajax对象
var oAjax = null
//此处必须需要使用window.的方式,表示为window对象的一个属性.不存在是值为undefined,进入else/若直接使用XMLHttpRequest在不支持的情况下会报错
if (window.XMLHttpRequest) {
oAjax = new XMLHttpRequest();
} else {
//IE6+
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.连接服务器
//open(method ,url, async)
oAjax.open("GET", url, true);
//3.发送请求
oAjax.send();
//4.接收返回
//OnRedayStateChange事件
oAjax.onreadystatechange = function () {
if (oAjax.readyState === 4) {
if (oAjax.status === 200) {
fnSucc(oAjax.responseText);
} else {
if (fnFaild) {
fnFaild();
}
}
}
};

使用Ajax

基础:请求并显示静态TXT文件

  • 字符集编码:不一致时会出现乱码
  • 缓存,阻止缓存,(使用时间对象添加)

动态数据:请求JS(或JSON)文件

  • 并不推荐使用eval,并不推荐使用eval,并不推荐使用eval。因为eval解析数据时会有一系列问题出现。这里是因为只是学习就随意点了。
  • 在需要解析请求数据时,推荐使用JSON的方法JSON.parse()可以将一个 JSON 字符串解析成为一个 JavaScript 值。参考 MDN-JSON

安全限制

上面代码的URL使用的是相对路径。如果不是相对路径的话,运行肯定报错。在Chrome的控制台里,还可以看到错误信息。

这是因为浏览器的同源策略导致的。默认情况下,JavaScript在发送AJAX请求时,URL的域名必须和当前页面完全一致。完全一致的意思是,域名要相同(www.example.com和example.com不同),协议要相同(http和https不同),端口号要相同(默认是:80端口,它和:8080就不同)。有的浏览器口子松一点,允许端口不同,大多数浏览器都会严格遵守这个限制。

那是不是用JavaScript无法请求外域(就是其他网站)的URL了呢?方法还是有的,大概有这么几种:

  • 一是通过Flash插件发送HTTP请求,这种方式可以绕过浏览器的安全限制,但必须安装Flash,并且跟Flash交互。不过Flash用起来麻烦,而且现在用得也越来越少了。

  • 二是通过在同源域名下架设一个代理服务器来转发,JavaScript负责把请求发送到代理服务器:

    1
    '/proxy?url=http://www.sina.com.cn'

代理服务器再把结果返回,这样就遵守了浏览器的同源策略。这种方式麻烦之处在于需要服务器端额外做开发。

  • 第三种方式称为JSONP,它有个限制,只能用GET请求,并且要求返回JavaScript。这种方式跨域实际上是利用了浏览器允许跨域引用JavaScript资源

Ajax函数的封装

众所周知,封装的目的是为了更好的重构,便于后期维护,在大项目中更能体现封装的好处,Ajax在网页中又是经常使用到的,所以我们来学习下怎么对Ajax函数进行封装,用前面get请求的例子进行演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* AJAX函数封装
* @param {string} url 请求地址(必须)
* @param {object} options 发送请求的选项参数
* @config {string} [options.type] 请求发送的类型。默认为GET。
* @config {Object} [options.data] 需要发送的数据。
* @config {Function} [options.onsuccess] 请求成功时触发,function(oAjax.responseText, oAjax)。(必须)
* @config {Function} [options.onfail] 请求失败时触发,function(oAjax)。(oAJax为XMLHttpRequest对象)
* @returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
*/

function AJAX(url, options) {
//1.创建ajax对象
var oAjax = null;
/**
* 此处必须需要使用window.的方式,表示为window对象的一个属性.不存在时值为undefined,进入else
* 若直接使用XMLHttpRequest,在不支持的情况下会报错
**/

if (window.XMLHttpRequest) {
//IE6+
oAjax = new XMLHttpRequest();
} else {
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}

//2.连接服务器
//open(方法,url,是否异步)
var param = ""; //请求参数。
//只有data存在,且为对象使才执行
var data = options.data ? options.data : -1; //缓存data
if (typeof (data) === "object") {
for (var key in data) { //请求参数拼接
if (data.hasOwnProperty(key)) {
param += key + "=" + data[key] + "&";
}
}
param.replace(/&$/, "");
} else {
param = "timestamp=" + new Date().getTime();
}

//3.发送请求
var type = options.type ? options.type.toUpperCase() : "GET";
if (type === "GET") {
oAjax.open("GET", url + "?" + param, true);
oAjax.send();
} else {
oAjax.open("POST", url, true);
oAjax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
oAjax.send(param);
}

//4.接收返回
//OnRedayStateChange事件
oAjax.onreadystatechange = function () {
if (oAjax.readyState === 4) {
if (oAjax.status === 200) {
//请求成功。形参为获取到的字符串形式的响应数据
options.onsuccess(oAjax.responseText, oAjax);
} else {
//先判断是否存在请求失败函数
//存在时,形参为XMLHttpRequest对象,便于进行错误进行处理
if (options.onfail) {
options.onfail(oAjax);
}
}
}
};
return oAjax;//发送请求的XMLHttpRequest对象
}

另外一个Ajax封装实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
*author: Ivan
*date: 2014.06.01
*参数说明:
*opts: {'可选参数'}
**method: 请求方式:GET/POST,默认值:'GET';
**url: 发送请求的地址, 默认值: 当前页地址;
**data: string,json;
**async: 是否异步:true/false,默认值:true;
**cache: 是否缓存:true/false,默认值:true;
**contentType: HTTP头信息,默认值:'application/x-www-form-urlencoded';
**success: 请求成功后的回调函数;
**error: 请求失败后的回调函数;
*/

function ajax(opts){
//一.设置默认参数
var defaults = {
method: 'GET',
url: '',
data: '',
async: true,
cache: true,
contentType: 'application/x-www-form-urlencoded',
success: function (){},
error: function (){}
};

//二.用户参数覆盖默认参数
for(var key in opts){
defaults[key] = opts[key];
}

//三.对数据进行处理
if(typeof defaults.data === 'object'){ //处理 data
var str = '';
for(var key in defaults.data){
str += key + '=' + defaults.data[key] + '&';
}
defaults.data = str.substring(0, str.length - 1);
}

defaults.method = defaults.method.toUpperCase(); //处理 method

defaults.cache = defaults.cache ? '' : '&' + new Date().getTime() ;//处理 cache

if(defaults.method === 'GET' && (defaults.data || defaults.cache)) defaults.url += '?' + defaults.data + defaults.cache; //处理 url

//四.开始编写ajax
//1.创建ajax对象
var oXhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
//2.和服务器建立联系,告诉服务器你要取什么文件
oXhr.open(defaults.method, defaults.url, defaults.async);
//3.发送请求
if(defaults.method === 'GET')
oXhr.send(null);
else{
oXhr.setRequestHeader("Content-type", defaults.contentType);
oXhr.send(defaults.data);
}
//4.等待服务器回应
oXhr.onreadystatechange = function (){
if(oXhr.readyState === 4){
if(oXhr.status === 200)
defaults.success.call(oXhr, oXhr.responseText);
else{
defaults.error();
}
}
};
}

调用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var ajax1 = ajax({
url: '1.php',
ata: {name: 'test', sex: 'male', age: '23'},
 success: function (data){ alert('返回数据是:' + data); }
});

var ajax2 = ajax({
url: '2.php',
data: 'name=test&sex=male&age=23',
  cache: false,
  success: function (data){ alert('返回数据是:' + data); },
error: function (){ alert('请求失败...')}
});

`

文章目录
  1. 1. 网页浏览过程分析
    1. 1.1. 一个完整的HTTP请求过程,通常有下面7个步骤
  2. 2. Ajax原理
    1. 2.0.1. 理解同步和异步(基本都用异步请求).
  • 3. HTTP请求
    1. 3.1. 一个HTTP请求一般由四部分组成
  • 4. HTTP响应
    1. 4.1. 一个HTTP响应一般由三部分组成:
    2. 4.2. 常见的HTTP请求方式
    3. 4.3. 编写Ajax
      1. 4.3.1. 1、创建Ajax对象
      2. 4.3.2. 2、连接服务器
      3. 4.3.3. 3、发送请求
      4. 4.3.4. 4、接受返回(XMLHttpRequset取得响应)
      5. 4.3.5. 通过监听onreadystatechange事件,来判断请求的状态(readyState属性:响应返回所处状态).
    4. 4.4. 使用函数简单的封装一个get请求
    5. 4.5. 使用Ajax
      1. 4.5.1. 基础:请求并显示静态TXT文件
      2. 4.5.2. 动态数据:请求JS(或JSON)文件
    6. 4.6. 安全限制
      1. 4.6.1. 那是不是用JavaScript无法请求外域(就是其他网站)的URL了呢?方法还是有的,大概有这么几种:
    7. 4.7. Ajax函数的封装
      1. 4.7.1. 众所周知,封装的目的是为了更好的重构,便于后期维护,在大项目中更能体现封装的好处,Ajax在网页中又是经常使用到的,所以我们来学习下怎么对Ajax函数进行封装,用前面get请求的例子进行演示
    8. 4.8. 另外一个Ajax封装实例