Ajax

1. XMLHttpRequest对象

XMLHttpRequest对象用于从JavaScript发出HTTP请求,下面是典型用法.

//新建一个XMLHttpRequest实例对象
var xhr = new XMLHttpRequest();
//指定通信过程中状态改变时的回调函数
xhr.onreadystatechange = function() {
    //通信成功时,状态值为4
    var completed = 4;
    if(xhr.readyState === completed){
        if(xhr.status === 200){
        //处理服务器发送过来的信息
        }else{
        //处理错误
        }
    }
};
//open方式用于指定HTTP动词,请求的网址,是否异步
xhr.open('GET', '/endpoint', true);

//发送HTTP请求
xhr.send(null);

Open()

  • 发送方法:”GET”,”POST”,”PUT”,”DELETE”
  • 网址
  • 是否异步,true表示异步,false表示同步
xhr.open('OPEN',9 encodeRUI('someURL'));
//设置HTTP请求的头信息
xhr.setRequestHeader('content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {};
//用于实际翻出HTTP请求,如果不带参数,只包含头信息,如:GET;如果有参数,还带有具体数据信息如:POST
xhr.send(encodeURI('dataString'));

send方法课发送许多类型的数据:

void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString data);
void send(FormData data);

Blob类型可以用来发送二进制数据,这使得通过Ajax上传文件成为可能。

readyState属性和readyStateChange事件
通信过程中,每当状态发生改变,readyState属性的值就会改变
这个值每改变一次,都会触发readyStateChange事件.我们可以指定这个事件的回调函数,对不同状态进行处理.

progress事件
上传文件时,XMLHttpRequest对象的upload属性有一个progress,会不断返回上传进度.

服务器返回的信息

status属性
返回HTTP状态码.
responseText属性
服务器返回的文本数据

setRequestHeader方法

用于设置HTTP头信息

xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
xhr.send(JSON.stringify(data));

overrideMimeType方法

指定服务器返回数据的MIME类型.
如果希望从服务器取回二进制数据,就要使用这个方法,认为将数据类型伪装成文本数据.

responseType属性

XMLHttpRequest对象有一个responseType属性,用来指定服务器返回数据(xhr.response)的类型.

  • ‘text’:返回了性为字符串,默认值
  • ‘arraybuffer’: 返回类型为ArrayBuffer
  • ‘blob’: 返回类型为Blob
  • ‘document’: 返回类型为Document
  • ‘json’: 返回类型为JSON object

文件上传

<form id="file-form" action="handler.php" method="post">
    <input type="file" id="file-select" name="photos[]" multiple />
    <button type="submit" id="upload-button">上传</button>
</form>

HTML代码中,file控件的multiple属性,可以指定一次选多个文件
file对象的files属性,返回一个FileList对象

var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;

//新建一个FormData对象实例,模拟发送到服务器的表单数据
var formData = new FormData();
for ( var i = 0;i < files.length;i++ ){
    var file = file[i];

    if(!file.type.match('image.*')) {
        continue;
    }
    formData.append('photos[]', file, file.name);
}

//最后使用Ajax方法向服务器上传文件
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.php', true);

xhr.onload = function() {
    if(xhr.status !== 200) {
        alert('An error occurred!');
    }
}
xhr.send(formData);

//除了FormData接口上传,也可以直接使用FileAPI上传
var file = document.getElementById('test-input').files[0];
var xhr = new XMLHttpRequest();

xhr.open('POST', 'muserver.uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);

FormData对象的append方法,除了可以添加文件,还可以添加二进制对象(Blob)或者字符串。第一个参数是表单的控件名,第二个参数是实际的值,第三个参数是可选的,通常是文件名。

JSONP

用于服务器与客户端之间的数据传输,主要为了规避浏览器的同域限制.

function addScriptTag(src){
    var scipt = document.createElement('script');
    script.setAttribute("type", "text/javascript");
    script.src = src;
    document.body.appendChild(script);
}

window.onload = function(){
    addScriptTag("HTTP://example.com/ip?callback=foo");
}
function foo(data) {
    console.log('your public IP address is: ' + data.ip);
}

许多服务器支持JSONP指定回调函数的名称,直接将JSON数据放入回调函数的参数,如此一来就省略了将字符串解析为JSON对象的步骤。

jQuery的 getJSON方法就是JSONP的一个应用

$.getJSON("http://example.com/api", function(data){})

CORS “跨域资源共享”(Cross-origin resource sharing)

允许JavaScript代码向另一个域名发出XMLHttpRequest请求,从而克服了传统上Ajax只能在同一个域名下使用的限制(same origin security policy)

//检查浏览器是否支持的代码如下
var request = new XMLHttpRequest();

if("withCredentials" in request) {

}

服务器回应的都有一个:Access-Control-Allow-Origin头信息.

Fetch API

Ajax操作所用的XMLHttpRequestRquest对象,已经有十多年的历史了,它的API设计并不是很好,输入、输出、状态都在同一个接口管理,容易出现混乱的代码.Fetch API是一种新规范,用来取代XMLHttpRequest对象.它主要有两个特定,一是简化接口,将API分散在几个不同的对象上,二是返回Promise对象,避免嵌套的回调函数.
检查浏览器是否部署了这个API的代码如下:

if (fetch in window){
    //支持
}else {
    //不支持
}

fetch API简单例子

var URL = 'http://some/path';
fetch(URL).then(function(response) {
    return response.json();
}).then(function(json) {
    someOperator(json);
});

上面代码向服务器请求JSON文件,获取后再做进一步处理.

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}
function reqError(err) {
    console.log('Fetch Error : -S', err);
}
var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

Fetch操作

fetch('./api/some.json')
    .then(function(response) {
        if(response.status !== 200){
        console.log('请求失败,状态码: ' + response.status);
        return;
}
response.json().then(function(data) {
    console.log(data);
});
}).catch(function(err){
    console.log('出错: ', err);
});

因为HTTP请求返回的response对象是一个Stream对象,所以需要使用response.json方法转为JSON格式,不过这个方法返回的是一个Promise对象。
* fetch()*
fetch方法的第一个参数可以是URL字符串,也可以是后文要讲到的Request对象实例.Fetch方法返回一个Promise对象,并将一个response对象传给回调函数.

发出POST请求的写法如下:

fetch("http://www.example.org/submit.php", {
    method: "POST",
    header: {
    "content-Type": "application/x-www-form-urlencoded"
},
body: "firstName=nik&sdfs=blue&password=sdfs"
}).then(function(res) {
    if(res.ok) {
    console.log("Perfect!your settings are saved");
} else if(res.status == 401) {
    console.log("oops,You are not authorized.");
}
},function(e) {
    console.log("Error submitting form!");
});

Headers
Fetch API引入三个新的对象(构造函数): Header,Request和Response.

reqHeaders = new Headers({
    "Content-Type": "text/plain",
    "Content-Length": content.length.toString(),
    "x-Custom-Header": "ProcessThisImmediately"
});

//headers实例构造Response方法
var response = new Response(
    JSON.stringify({photos: {photo: []}}),
    {'status': 200, headers: headers}
);
response.json().then(function(json) {
    insertPhotos(json);
});

Request

//Request对象用来构造HTTP请求
var req = new Request('/index.html');
req.method  //"GET"
req.url  //"http://example.com/index.html"

//Request对象的第二个参数,表示配置对象
var uploadReq = new Request("/uploadImage", {
    method: "POST",
    headers: {
    "Content-Type": "image/png",
},
body: "image data"
});

Response

  • status:整数值,表示状态码(比如200)
  • statusText:字符串,表示状态信息,默认是“OK”
  • ok:布尔值,表示状态码是否在200-299的范围内
  • headers:Headers对象,表示HTTP回应的头信息
  • url:字符串,表示HTTP请求的网址
  • type:字符串,合法的值有五个basic、cors、default、error、opaque。basic表示正常的同域请求;cors表示CORS机制的跨域请求;error表示网络出错,无法取得信息,status属性为0,headers属性为空,并且导致fetch函数返回Promise对象被拒绝;opaque表示非CORS机制的跨域请求,受到严格限制。

Response对象还有两个静态方法。

  • Response.error() 返回一个type属性为error的Response对象实例
  • Response.redirect(url, status) 返回的Response对象实例会重定向到另一个URL

body属性
Request对象和Response对象都有body属性,表示请求的内容。body属性可能是以下的数据类型。

  • ArrayBuffer
  • ArrayBufferView (Uint8Array等)
  • Blob/File
  • string
  • URLSearchParams
  • FormData

Request对象和Response对象都提供以下方法,用来读取body。

  • arrayBuffer()
  • blob()
  • json()
  • text()
  • formData()

Request对象和Response对象都有bodyUsed属性,返回一个布尔值,表示body是否被读取过。

如果希望多次使用body属性,可以使用Response对象和Request对象的clone方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章