Ajax

服务器、网络基础、相关知识介绍

服务器介绍:

常见的服务器软件有:

  • 文件服务器:Server-U、FileZilla、VsFTP等(FTP是File Transfer Protocol文件传输协议);
  • 数据库服务器:oracle、mysql、SQL server、DB2、ACCESS等;
  • 邮件服务器:Postfix、Sendmail等;
  • HTTP服务器:Apache、Nginx、IIS、Tomcat、NodeJS等;

按照不同的划分标准,服务可划分为以下类型:

(1) 服务器类型

  • 服务类型 可分为:
    • 文件服务器
    • 数据库服务器
    • 邮件服务器
    • Web服务器等;
  • 操作系统 可分为:
    • Linux服务器
    • Windows服务器等;
  • 应用软件 可分为
    • Apache 服务器
    • Nginx 服务器
    • IIS 服务器
    • Tomcat 服务器
    • weblogic 服务器
    • WebSphere 服务器
    • boss 服务器
    • Node 服务器等

(2) HTTP服务器

  • 即网站服务器,主要提供文档(文本、图片、视频、音频)浏览服务,一般安装Apache、Nginx服务器软件。
  • HTTP服务器可以结合某一编程语言处理业务逻辑,由此进行的开发,通常称之为服务端开发
  • 常见的运行在服务端的编程语言包括 php、java、.net、Python、Ruby、Perl等。

(3) 客户端介绍:

  • 具有向服务器索取服务能力的终端,如比如 手机、电脑等,通过安装不同的客户端软件,可以获取不同的服务,比如通过QQ获得即时通讯服务、通过迅雷获得下载服务等。
  • 常见的客户端软件:浏览器、QQ、迅雷、Foxmail等。
  • 以浏览器为宿主环境,结合 HTML、CSS、Javascript等技术,而进行的一系列开发,通常称之为前端开发

网络基础:

IP地址

  • 所谓IP地址就是给每个连接在互联网上的主机分配的一个32位地址。(就像每部手机能正常通话需要一个号码一样)
  • 查看本机IP地址 ping、ipconfig、ifconfig(linux)

域名

  • 由于IP地址基于数字,不方便记忆,于是便用域名来代替IP地址,域名是一个IP地址的“面具”
  • 查看域名对应的IP地址 ping

DNS服务

  • DNS(Domain Name System)因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
  • 简单的说就是记录IP地址和域名之间对应关系的服务。
  • 查找优先级 本机 hosts 文件、DNS服务器
  • ipconfig /flushdns 刷新DNS

端口

  • 端口号是计算机与外界通讯交流的出口,每个端口对应不同的服务。现实生活中,银行不同的窗口办理不同的业务。
  • 查看端口占用情况 netstat -an
  • 常见端口号 80、8080、3306、21、22

软件架构

C/S结构

Client、Server

  • 在C/S结构的情况下,不同的服务需要安装不同的客户端软件,
  • 比如QQ、迅雷、Foxmail 这种情况下安装的软件会越来越多,同时也有许多弊端,比如A出差,需要在B电脑上查收邮件,但是B电脑并未安装Foxmail等类似的客户端软件,这样不得不先去下载Foxmail,非常不方便。

B/S结构

Broswer、Server

  • 解决了C/S所带来的不便
  • 将所有的服务都可以通过浏览器来完成(因为基本所有浏览器都安装了浏览器),但B/S也有一些不利,比如操作稳定性、流畅度等方面相对较弱。

网络传输协议

常见协议

  • HTTP、HTTPS 超文本传输协议
  • FTP 文件传输协议
  • SMTP 简单邮件传输协议

http协议

  • 超文本传输协议(HTTP,HyperText Transfer Protocol) 网站是基于HTTP协议的,例如网站的图片、CSS、JS等都是基于HTTP协议进行传输的。
  • HTML Hypertext Markup Language
  • HTTP协议是由从客户机到服务器的请求(Request)和从服务器到客户机的响应(Response)进行了约束和规范。即HTTP协议主要由请求和响应构成。

常用请求方法 POSTGET、PUT、DELETE

请求由 4 部分组成

  • HTTP 请求方法或 “动作”
  • 正在请求的 URL
  • 一个可选的请求头集合。其中可能包括身份验证信息
  • 一个可选的请求体

请求头

由请求方式、请求URL和协议版本构成

  • GET /day01/code/login.php?username=123&password=123 HTTP/1.1
  • POST /day01/code/login.php HTTP/1.1

请求行

  • Host:localhost
    • 请求的主机,发出请求的页面所在的域
  • Cache-Control:max-age=0
    • 控制缓存
  • Accept
    • / 接受的文档MIME类型
  • User-Agent
    • 很重要,浏览器的用户代理字符串
  • Referer
    • 从哪个URL跳转过来的,发出请求的页面 URL
  • Accept-Encoding
    • 可接受的压缩格式
  • If-None-Match
    • 记录服务器响应的ETag值,用于控制缓存,此值是由服务器自动生成的
  • If-Modified-Since
    • 记录服务器响应的Last-Modified值,此值是由服务器自动生成的
  • Accept-Charset
    • 浏览器能够显示的字符集
  • Accept-Language
    • 浏览器当前设置的语言
  • Connection
    • 浏览器和服务器之间连接的类型
  • Cookie
    • 当前页面设置的任何 Cookie

请求主体

  • 即传递给服务端的数据
  • 注:当以post形式提交表单的时候,请求头里会设置
  • Content-Type: application/x-www-form-urlencoded,以get形式当不需要

响应和响应报文

响应由服务器发出,其规范格式为:状态行、响应头、响应主体。

服务器返回的 HTTP 响应包含 3 部分

  • 一个数字和文字组成的状态码,用来显示请求的成功和失败
  • 一个响应头集合
  • 响应主体

状态行

由协议版本号、状态码和状态信息构成 HTTP/1.1 200 OK

响应头

  • Date
    • 响应时间
  • Server
    • 服务器信息
  • Last-Modified
    • 资源最后修改时间 由服务器自动生成
  • ETag
    • 资源修改后生成的唯一标识 由服务器自动生成
  • Content-Length
    • 响应主体长度
  • Content-Type
    • 响应资源的类型

响应主体

即服务端返回给客户端的内容;

状态码,常见的有:

  • 200代表成功
  • 304文档未修改
  • 403没有权限
  • 404未找到
  • 500服务器错误

JavaScript 原生的 Ajax

Ajax 的技术核心是 XMLHttpRequest 对象。AJAX 不是一门的新的语言,而是对现有技术的综合利用。本质是在HTTP协议的基础上以异步的方式与服务器进行通信。

异步

指某段程序执行时不会阻塞其它程序执行,其表现形式为程序的执行顺序不依赖程序本身的书写顺序,相反则为同步。

其优势在于不阻塞程序的执行,从而提升整体执行效率。

XMLHttpRequest 对象

浏览器内建对象,用于在后台与服务器通信(交换数据) ,由此我们便可实现对网页的部分更新,而不是刷新整个页面。

HTTP请求3个组成部分与XMLHttpRequest方法的对应关系

  • 请求行 xhr.open(‘post’,’01.php’);
  • 请求头 xhr.setRequestHeader(‘Content-Type’,’application/x-www-form-urlencoded’); get请求可以不设置
  • 请求主体 xhr.send(“name=xjj&age=10”); get 请求方式可以传空
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 适用于 IE7 之前的版本
function createXHR() {
if (typeof arguments.callee.activeXString != "string") {
var versions = [
"MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp.3.0",
"MSXML2.XMLHtt"
], i, len;
for (i = 0, len = versions.length; i < len; i++) {
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex) {
// 跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}

IE7+、FireFox、Opera、Chrome、Safari 都支持原生的 XHR 对象。

1
var xhr = new XMLHttpRequest();

封装获取 xhr 对象的函数

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
function createXHR() {
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined") {
if (typeof arguments.callee.activeXString != "string") {
var versions = [
"MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp.3.0",
"MSXML2.XMLHtt"
], i, len;
for (i = 0, len = versions.length; i < len; i++) {
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex) {
// 跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error ("No XHR object is available");
}
}

XMLHttpRequest 对象使用

  • open() 方法
    • 三个参数:
      • 要发送的请求的类型:(“get”, “post”)
      • 请求的 URL ,是相对于执行代码的当前页面(也可以使用绝对路径)
      • 表示是否异步发送请求的布尔值
    • 只能想用一个域中使用相同端口和协议的 URL 发送请求。如果 URL 与启动请求的页面有任何差别,都会发生安全错误。
1
2
xhr.open("get", "exam.php", false);
xhr.send(null);
  • send() 方法
    • 一个参数,请求主题发送的数据
    • 如果不需要请求主体发送数据,必须传入 null 值,调用完之后请求就发会被分派到服务器。

由于这次请求是同步的,JavaScript 代码会等到服务器响应之后再继续执行。在收到响应后 ,响应的数据会自动填充 XHR 对象的属性。属性说明如下:

  • responseText: 作为响应主体被返回的文本。
  • responseXML: 如果响应的内容是 “text/xml” 或 “application/xml”,这个属性中保存着响应数据的 XML DOM 文档。
  • status: 响应的 HTTP 状态。
  • statusText: HTTP 状态说明。

在收到响应后,第一步就是检查 status 属性,以确定响应已经成功返回。一般来说,可以将 状态代码为 200 作为成功的标志。此时,responseText 属性的内容已就绪,而且在内容正确的时候,responseXML 也能够访问了。此外,状态码为 304 表示请求的资源并没有被修改,可以直接使用浏览器缓存的版本;也意味着响应是有效的。因此,检查状态码:

1
2
3
4
5
6
7
xhr.open("get", "exam.php", false);
xhr.send(null);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText);
} else {
console.log("请求失败: " + xhr.status);
}

前面这样发送同步请求没有问题,但是发送异步请求时,才能让 JavaScript 继续执行而不必等待响应。可以通过检测 XHR 对象的 readyState 属性,该属性表示请求/响应过程的当前活动阶段。该属性的取值:

  • 0 未初始化,即尚未调用 open() 方法
  • 1 启动,已经调用 open() 方法,但尚未调用 send()
  • 2 发送,已经调用 send() 方法,但尚未接收到响应,请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
  • 3 接收,已经接收到部分响应数据,请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成。
  • 4 完成,已经接收到全部响应数据,而且已经可以在客户端使用了

只要 readyState 属性的值由一个值变成另一个值,都会触发 readystatechange 事件。可以利用这个事件来检测每次状态变化后 readyState 值。通常,我们只对 readyState 值为 4 的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用 open() 之前指定 onreadystatechange 事件处理程序才能确保跨浏览器兼容性。代码如下:onreadystatechangeJavascript的 事件的一种,其意义在于监听 XMLHttpRequest 的状态

  • 获取状态行(包括状态码&状态信息)
    • xhr.status 状态码;
    • xhr.statusText 状态码信息
  • 获取响应头
    • xhr.getResponseHeader('Content-Type');
    • xhr.getAllResponseHeaders();
  • 响应主体
    • xhr.responseText;
    • xhr.responseXML
1
2
3
4
5
6
7
8
9
10
11
12
var xhr = createXHR();
xhr.onreadystatechange = function() {
if (xhr.readState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText);
} else {
console.log("请求失败: " + xhr.status);
}
}
};
xhr.open("get", "exam.php", true);
xhr.send(null);

在接收到响应之前还可以调用 abort() 方法来取消异步请求。

1
xhr.abort();

setRequestHeader()方法可以设置自定义的请求头部信息。这个方法接收两个参数:

  • 头部名称
  • 头部字段的值

setRequestHeader()方法必须在调用 open() 方法之后,send() 方法之前调用.

GET 请求

GET 请求将查询的字符串参数追加到 URL 的末尾,传入 open() 方法的 URL 末尾的查询字符串必须经过正确的编码才行。

查询字符串中的每个值都必须经过 encodeURLComponent() 进行编码,然后才能放到 URL 末尾。

所有的名-值对都必须由(&)符号分隔。如:

1
xhr.open("get", "exam.php?name=value&name=value2", true);

封装经过编码的查询字符串。

1
2
3
4
5
6
// 向 URL 末尾添加查询字符串的方法
function addURLParam(url, name, value) {
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURLComponent(name) + "=" + encodeURLComponent(value);
return url;
}

POST 请求

通常用于向服务器发送应该保存的数据。POST 请求应该把数据作为请求的主体提交。给 open() 方法的第一个参数传入 “post” 就可以初始化一个 post 请求。

1
xhr.open("post", "exam.php", true);

使用 XHR 来模仿表单提交:首先将 Content-Type 头部设置为 application/x-www-form-urlencoded ,也就是表单提交时的数据类型,其次是以适当的格式创建一个字符串。

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
function submitData() {
var xhr = createXHR();
xhr.onreadstatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText);
} else {
console.log("请求失败: " + xhr.status);
}
}
};
xhr.open("post", "exam.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById("userInfo");
xhr.send(serialize(form));
}
// 获取 XHR 对象的兼容方法
function createXHR() {
if (typeof arguments.callee.activeXString != "string") {
var versions = [
"MSXML2.XMLHttp.6.0",
"MSXML2.XMLHttp.3.0",
"MSXML2.XMLHtt"
], i, len;
for (i = 0, len = versions.length; i < len; i++) {
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex) {
// 跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
// 表单序列化函数
function serialize(form) {
var parts = [],
field = null,
i,
len,
j,
optLen,
option,
optValue;
for (i = 0, len = form.elements.length; i < len; i++) {
field = form.elements[i];
switch(field.type) {
case "select-one":
case "select-multipule":
if (field.name.length) {
for (j = 0, optLen = field.options.length; j < optLen; j++) {
option = field.options[j];
if (option.selected) {
optValue = "";
if (option.hasAttribute) {
optValue = (option.hasAttribute("value") ? option.value : option.text);
} else {
optValue = (option.attributes["values"].specified ? option.value : option.text);
}
parts.push(encodeURLComponent(field.name) + "=" + encodeURLComponent(optValue));
}
}
}
break;
case undefined:
case "file":
case "reset":
case "submit":
case "button":
break;
case "radio":
case "checkbox":
if (!field.name.length) {
break;
}
default:
if (field.name.length) {
parts.push(encodeURLComponent(field.name) + "=" + encodeURLComponent(field.value));
}
}
}
return parts.join("&");
}

注:GET和POST请求方式的差异

  • GET没有请求主体,使用xhr.send(null)
  • GET可以通过在请求URL上添加请求参数
  • POST可以通过xhr.send(‘name=itcast&age=10’)
  • POST需要设置
  • GET效率更好(应用多)
  • GET大小限制约4K,POST则没有限制

关于表单序列化

XMLHTTPRequest 2 级 定义了 FormData 类型。 FormData 为序列化表单以及创建与表单格式相同的数据。

1
2
var data new FormData();
data.append("name", "Hiraku");

append() 方法传递两个参数。即键和值。也可以使用如下的方式:

1
var data = new FormData(document.forms[0]);

创建了 FormData 的实例后,可以直接传递给 send() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var xhr = createXHR();
xhr.onreadstatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText);
} else {
console.log("请求失败: " + xhr.status);
}
}
};
xhr.open("post", "exam.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById("userInfo");
xhr.send(new FormDta(form));

超时设定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var xhr = createXHR();
xhr.onreadstatechange = function() {
try {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText);
} else {
console.log("请求失败: " + xhr.status);
}
}
} catch (e) {
// 由 ontimeout 事件程序处理
}
};
xhr.open("get", "exam.php", true);
xht.timeout = 1000; // 仅适用于 IE
xhr.ontimeout = funciton() {
console.log("请求失败:")
}
xhr.send(null);

进度事件

  • loadstart: 收到响应数据的第一个字节时触发
  • progress:在接收响应期间不断地触发
  • error: 发生错误时触发
  • abort: 调用 abort() 方法而终止时触发
  • load: 在接收到完整的响应数据时触发
  • loadend: 在通信完成或者触发 error、abort、或 load 事件后触发。

我们需要检测并判断响应头的 MIME 类型后确定使用 request.responseText 或者 request.responseXML

API 总结

  • xhr.open()
    • 发起请求,可以是get、post方式
  • xhr.setRequestHeader()
    • 设置请求头
  • xhr.send()
    • 发送请求主体get方式使用xhr.send(null)
  • xhr.onreadystatechange = function () {}
    • 监听响应状态
  • xhr.status
    • 表示响应码,如200
  • xhr.statusText
    • 表示响应信息,如OK
  • xhr.getAllResponseHeaders()
    • 获取全部响应头信息
  • xhr.getResponseHeader('key')
    • 获取指定头信息
  • xhr.responseText、xhr.responseXML
    • 都表示响应主体

封装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
71
72
73
74
75
76
77
78
79
80
81
82
/*
* 1. 请求的类型 type get post
* 2. 请求地址 url
* 3. 是异步的还是同步的 async false true
* 4. 请求内容的格式 contentType
* 5. 传输的数据 data json对象
* 6. 响应成功处理函数 success function
* 7. 响应失败的处理函数 error function
* 这些都是动态参数 参数对象 options
* */
window.$ = {};/*封装一个函数*/
/*申明一个ajax的方法*/
$.ajax = function(options){
if(!options || typeof options != 'object'){
return false;
}
/*请求的类型*/
var type = options.type || 'get';/*默认get*/
/*请求地址 */
var url = options.url || location.pathname;/*当前的地址*/
/*是异步的还是同步的 */
var async = (options.async === false)?false:true;/*默认异步*/
/*请求内容的格式 */
var contentType = options.contentType || "text/html";
/*传输的数据 */
var data = options.data || {};/*{name:'',age:''}*/
/*在提交的时候需要转成 name=xjj 这种格式*/
var dataStr = ''; /*数据字符串*/
for(var key in data){
dataStr += key+'='+data[key]+'&';
}
dataStr = dataStr && dataStr.slice(0,-1);
/*ajax 编程*/
var xhr = new XMLHttpRequest();
/*请求行*/
/*(type=='get'?url+'?'+dataStr:url)判断当前的请求类型*/
xhr.open(type,(type=='get'?url+'?'+dataStr:url),async);
/*请求头*/
if(type == 'post'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
}
/*请求主体*/
/*需要判断请求类型*/
xhr.send(type=='get'?null:dataStr);
/*监听响应状态的改变 响应状态*/
xhr.onreadystatechange = function(){
/*请求响应完成并且成功*/
if(xhr.readyState == 4 && xhr.status == 200){
/*success*/
var data = '';
var contentType = xhr.getResponseHeader('Content-Type');
/*如果我们服务器返回的是xml*/
if(contentType.indexOf('xml') > -1){
data = xhr.responseXML;
}
/*如果我们的服务器返回的是json字符串*/
else if(contentType.indexOf('json') > -1){
/*转化json对象*/
data = JSON.parse(xhr.responseText);
}
/*否则的话他就是字符串*/
else{
data = xhr.responseText;
}
/*回调 成功处理函数*/
options.success && options.success(data);
}
/*计时请求xhr.status不成功 他也需要的响应完成才认作是一个错误的请求*/
else if(xhr.readyState == 4){
/*error*/
options.error && options.error('you request fail !');
}
}
}
$.post = function(options){
options.type = 'post';
$.ajax(options);
}
$.get = function(options){
options.type = 'get';
$.ajax(options);
}

jQuery的ajax

jQuery为我们提供了更强大的Ajax封装

  • $.ajax({})
    • 可配置方式发起Ajax请求
  • $.get()
    • 以GET方式发起Ajax请求
  • $.post()
    • 以POST方式发起Ajax请求
  • $('form').serialize()
    • 序列化表单(即格式化key=val&key=val)
  • url
    • 接口地址
  • type
    • 请求方式
  • timeout
    • 请求超时
  • dataType
    • 服务器返回格式
  • contentType
    • 指定请求的 HTTP Content-Type
  • data
    • 发送请求数据
  • beforeSend: function () {}
    • 请求发起前调用
  • success
    • 成功响应后调用
  • error
    • 错误响应时调用
  • complete
    • 响应完成时调用(包括成功和失败)
  • timeout
    • 超时时间
  • cache
    • 对于 GET 请求
  • ifModified
    • 当为 true 时,jQuery 会为请求的每一个 URL 记录 Last-Modified 和 If-None-Match 响应头的值
  • global
    • 是否触发上面描述的 Ajax 请求过程中的事件

jQuery Ajax介绍

感谢您的支持!