JavaScript-ajax篇

ajax全称是异步 javascript 和 XML,用来和服务端进行数据交互的,让无刷新替换页面数据成了可能;

GET方式

1
2
3
4
5
6
7
8
9
var xhr=new XMLHttpRequest();  
xhr.open("get", "servlet?name=testParam", true); //请求类型,url参数,是否异步
xhr.send(null);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var ret = xhr.responseText;
alert(ret);
}
}

POST方式

1
2
3
4
5
6
7
8
9
10
var xhr=new XMLHttpRequest();  
xhr.open("post","servlet",true); //请求类型,url地址,是否异步
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");//必须在open后面
xhr.send("name=testParam"); //发送data数据
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
var ret=xhr.responseText;
alert(ret);
}
}

用promise 封装 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
// ajax函数将返回Promise对象:
function ajax(method, url, data) {
var request = new XMLHttpRequest();
return new Promise(function(resolve, reject) {
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
resolve(request.responseText);
} else {
reject(request.status);
}
}
};
request.open(method, url);
request.send(data);
});
}

var p = ajax('GET', '/api/categories');

p.then(function(text) { // 如果AJAX成功,获得响应内容
console.log(text)
}).catch(function(status) { // 如果AJAX失败,获得响应代码
console.log('Error:', status)
});

ajax的优缺点

优点:
1.无刷新更新数据,优秀的用户体验
2.ajax不需要任何插件支持,可以被大多数主流浏览器支持
3.减少服务器和带宽的负担。在客户端创建ajax引擎,把传统方式下的服务器负担的工作转移到客户端,便于客户端资源来处理,减轻服务器和带宽的负担。

缺点:
1.浏览器对XMLHttpRequest对象支持度不足。ajax大量的使用了javascript和ajax引擎,这些取决于浏览器的支持.在编写的时候考虑对浏览器的兼容性.
2.破坏浏览器前进和后退按钮。ajax只是局部刷新,所以页面的后退按钮是没有用的.
3.开发和调试工具的缺乏。js是ajax的主要组成部分,但是缺少很好的js开发和调试工具。

ajax跨域

为什么会出现跨域问题?

出于浏览器的同源策略限制,浏览器会拒绝跨域请求。
注:严格的说,浏览器并不是拒绝所有的跨域请求,实际上拒绝的是跨域的读操作。

什么情况才算作跨域?

A:非同源请求,均为跨域。名词解释:同源 —— 如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面就属于同一个源(origin)。

最常用的跨域方式有以下三种:JSONP、CORS、postMessage

JSONP
单纯地为了实现跨域请求而创造的一个 trick。【实现原理】虽然因为同源策略的影响,不能通过XMLHttpRequest请求不同域上的数据(Cross-origin reads)。但是,在页面上引入不同域上的js脚本文件却是可以的(Cross-origin embedding)。因此在js文件载入完毕之后,触发回调,可以将需要的data作为参数传入。
【实现方式(需前后端配合)】

1
2
3
4
5
6
7
8
9
10
<script type="text/javascript">
function dosomething(data){
//处理获得的数据
}
</script>
<script src="http://example.com/data.php?callback=dosomething"></script><?php
$callback = $_GET['callback'];//得到回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
?

【JSONP的优缺点】
优点:兼容性好(兼容低版本IE)
缺点:

1.JSONP只支持GET请求;

2.XMLHttpRequest相对于JSONP有着更好的错误处理机制

CORS 是W3C 推荐的一种新的官方方案,能使服务器支持 XMLHttpRequest 的跨域请求。CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

服务端(node)

1
2
3
res.setHeader('Access-Control-Allow-Origin',req.header.origin);
res.setHeader('Access-Control-Allow-Credentails',true);//告诉客户端可以在http请求中加上cookie
res.setHeader('Access-Control-Allow-Method','POST,GET,PUT,DELETE,OPTIONS')

CORS由于存在兼容性问题,所以使用的时候需要做特殊判断

与JSONP的比较
CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。
JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

附注:理解promise

看一段很简单的代码,请注意阅读代码中的注释。

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
var val = 1;

// 我们假设step1, step2, step3都是ajax调用后端或者是
// 在Node.js上查询数据库的异步操作
// 每个步骤都有对应的失败和成功处理回调
// 需求是这样,step1、step2、step3必须按顺序执行
function step1(resolve, reject) {
console.log('步骤一:执行');
if (val >= 1) {
resolve('Hello I am No.1');
} else if (val === 0) {
reject(val);
}
}

function step2(resolve, reject) {
console.log('步骤二:执行');
if (val === 1) {
resolve('Hello I am No.2');
} else if (val === 0) {
reject(val);
}
}

function step3(resolve, reject) {
console.log('步骤三:执行');
if (val === 1) {
resolve('Hello I am No.3');
} else if (val === 0) {
reject(val);
}
}

new Promise(step1).then(function(val){
console.info(val);
return new Promise(step2);
}).then(function(val){
console.info(val);
return new Promise(step3);
}).then(function(val){
console.info(val);
return val;
}).then(function(val){
console.info(val);
return val;
});

console.log('外部步骤:执行')

// 执行之后将会打印
步骤一:执行
外部步骤:执行
Hello I am No.1
步骤二:执行
Hello I am No.2
步骤三:执行
Hello I am No.3
Hello I am No.3

笔者认为,Promise的意义就在于 then 链式调用 ,它避免了异步函数之间的层层嵌套,将原来异步函数的 嵌套关系 转变为便于阅读和理解的 链式步骤关系 。

Promise常用的关键点

在Promise定义时,函数已经执行了
Promise构造函数只接受一个参数,即带有异步逻辑的函数。这个函数在 new Promise 时已经执行了。只不过在没有调用 then 之前不会 resolve 或 reject。

在then中的resolve方法中如何return?
在then方法中通常传递两个参数,一个 resolve 函数,一个 reject 函数。reject暂时不讨论,就是出错的时候运行的函数罢了。resolve 函数必须返回一个值才能把链式调用进行下去,而且这个值返回什么是有很大讲究的。

resolve 返回一个新 Promise

返回一个新Promise之后再调用的then就是新Promise中的逻辑了。

resolve 返回一个值

返回一个值会传递到下一个then的resolve方法参数中。

就先分享到这吧,待续补充知识点和更新~~