0x0E

Summer Training Day 15.

Ajax
前端工程化


Ajax

Asynchronous JavaScript and XML.
异步js与XML

XMLHttpRequest对象.

Ajax技术的核心
XHR对象的构建要利用XMLHttpRequest构造函数.

1
2
var xhr = new XMLHttpRequest();
//IE7+版本.

用法

1
2
//三个参数
xhr.open("get","example","false");//类型--URL--是否异步发送

这个代码会启动一个针对example的GET请求.
URL相对于执行代码的当前页面(绝对路径也行)
调用open()方法并不会真正发送请求,而只是启动一个请求以备发送.
如果URL与启动请求的页面有任何差别都会报错.

使用send()发送请求:

1
2
xhr.send(null);
//一个参数

参数的意思是 要请求主体发送的数据.如果不需要则必须写null.

收到相应后,响应的数据自动填充xhr对象属性.

1
2
3
4
responseText: //被返回的文本.
responseXML: //若响应的内容类型是 text.xml 或者 application/xml ,这个属性将保存XML DOM文档.
status: //响应的HTTP状态.状态码200为正常,304为资源未被修改.
statusText: //HTTP状态说明.

检查响应情况.

1
2
3
4
5
6
7
8
9
var xhr = new XMLHttpRequest();
xhr.open("get","example","false");
xhr.send(null);
if ( (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log (xhr.responseText);
}else {
console.log ( "Request was unsuccessful: " + xhr.status );
}

readyState

1
2
3
4
5
6
0 : 未初始化(还没调用open()方法)
1 : 启动,已经调用open()方法,但未调用send().
2 : 发送,已经调用send()方法,但未收到响应.
3 : 接受,已经接收到部分响应数据.
4 : 完成,就能够完全接受响应数据,而且已经可以在客户端使用.

只要readyState属性值变化,都会触发一次readyStatechange事件.

1
2
3
4
5
6
7
8
9
10
11
12
var xhr = new XMLHttpRequest();
xhr.onreadyStatechange = function(){
if(xhr.readyState == 4){
if ( (xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log (xhr.responseText);
}else {
console.log ( "Request was unsuccessful: " + xhr.status );
}
}
};
xhr.open("get","example","false");
xhr.send(null);

接收到响应之前可以用abort来取消异步请求,取消之后还要解引用.

1
xhr.abort();


GET & POST


GET 请求(最常见)

-从指定资源请求数据-
-URL最大长度为2048个字符-
-安全性较差,因为发送的数据是URL一部分且数据对所有人可见-
-只允许ASCII字符-
传入open()方法的URL必须经过正确的编码.
每个参数的 name & value 都必须使用encodeURIComponent()进行编码.
然后才能放到URL末尾,且所有name-value都必须由 “&” 分隔.

1
2
3
4
5
6
7
8
9
xhr.open("get","example.php?name1=value1&value2",true);
```
辅助添加函数:
```javascript
function addURLParam(url,name,value){
url += (url.indexOf("?") == -1 ? "?" : "&");
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}

使用:

1
2
3
4
5
6
7
8
var url = "example.php";
//添加参数
url = addURLParam(url,"name","Nicholas");//之前全写错了写成Nicolas了.
url = addURLParam(url,"book","Professional JavaScript");
//初始化请求
xhr.open("get",url,false);

使用addURLParam()函数可以确保格式良好.

POST 请求

-向指定资源提交要被处理的数据-
与GET不同,post请求的主体可以包含非常多数据且格式不限.
post不会被缓存,不会在浏览器历史记录中.对长度无要求.
GET请求的速度最大可以达到POST的两倍.


XHR 2.


老版本不足:

1.只支持文本数据的传送,无法用来读取和上传二进制文件。
2.传送和接收数据时,没有进度信息,只能提示有没有完成。
3.受到”同域限制”(Same Origin Policy),只能向同一域名的服务器请求数据。

新版本特性:

1.可以设置HTTP请求的时限。 (timeout)
2.可以使用FormData对象管理表单数据。 (FormData)
3.可以上传文件。 ()
4.可以请求不同域名下的数据(跨域请求)。 ()
5.可以获取服务器端的二进制数据。
6.可以获得数据传输的进度信息。

详述.

以下摘自:
阮一峰:XMLHttpRequest Level 2 使用指南


1.timeout.

1
2
3
4
5
6
xhr.timeout = 3000; //3秒后自动停止HTTP请求.
//与之配对的ontimeout事件.
xhr.ontimeout = function(event){
console.log("请求超时!");
}

2.FromData.

1
2
3
4
var fromData = new FromData();
fromData.append("username","Nicholas");
fromData.append("book","Professional JavaScript");
xhr.send(fromData);

3.上传文件.

1
2
3
4
5
var fromData = new FromData();
for(i = 0 ; i < files.length ; i++){
fromData.append("files[]",files[i]);
}
xhr.send(fromData);

4.跨资源共享CORS.(Cross-origin resource sharing).

前提: a)浏览器支持. b)服务器同意.

1
xhr.open('GET', 'http://other.server/and/path/to/script');

5.接收二进制数据.

5.1(方法A.改写MIME类型)

原理(from高程) : 返回的MIME类型决定XHR该如何处理它.

基本原理是将服务器返回的非文本数据伪装成文本数据,并告诉浏览器这是用户自定义的字符集.

1
2
3
4
5
6
7
8
xhr.overrideMimeType("text/plain; charset=x-user-defined");
var binStr = xhr.responseText; //用responseText接收二进制数据.
//由于此时浏览器把它当作文本数据,所以要一个一个还原.
for(var i = 0, len = binStr.length; i< len; i++){
var c = binStr.charCodeAt(i);
var byte = c & 0xff;
}
//最后一行的位运算"c & 0xff",表示在每个字符的两个字节之中,只保留后一个字节,将前一个字节扔掉。原因是浏览器解读字符的时候,会把字符自动解读成Unicode的0xF700-0xF7ff区段。

5.2(方法B.responseType属性)

1
2
3
4
5
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = 'blob';
//接收数据的时候用浏览器自带的Blob对象
var blob = new Blob([xhr.response],{type: "img/png"});

用arrayBuffer替代responseType可以把二进制数据存放在数组中,但是接收的时候需要遍历.(详见链接)

6.progress进度条.

1
2
3
4
5
6
7
8
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
function updateProgress(event) {
  if (event.lengthComputable) {
    var percentComplete = event.loaded / event.total;
  }
}

与progress相关的还有5个事件,具体看链接.


前端工程化

含义:
1.持续集成.(git)
2.规范化.
3.模块化.
4.单元和功能测试.
5.自动化.
以上5点摘自红莲


个人理解就是团队效率个人效率,以前者为主.
团队合作一个项目的时候需要建立各自分支之后合并,为了大限度防止冲突,开始的分工很重要,这也涉及到第三点模块化,有点类似C的模块化编程,分功能分模块地编程,能够减少冲突并且使每位成员的时间和精力得到充分利用.团队成员一致地遵守一定的规范会让整体更加干净,增强可读性和可维护性.测试的作用也很显著,每个分部都测试好了,之后合并的问题就不会过分涉及部分模块,而偏向整体或接口.自动化是方便每位程序员提高效率的,每个人效率都提高了团队效率自然就高.
总之,工程化是个好东西.在从个人练习向团队项目转化时应该耗费一些精力和时间去学习践行工程化来使得团队得益.



以上.