JavaScript权威指南读书笔记——第十八章 脚本化HTTP

来源:互联网 发布:java微信企业号开发 编辑:程序博客网 时间:2024/06/14 20:09

使用XMLHttpRequest

浏览器在XMLHttpRequest类上定义了它们的Http API。这个类的每个实例都表示一个独立的请求/响应对,并且这个对象的属性和方法允许指定请求细节和提取响应属性。

使用这个Http API必须做的第一件事就是实例化XMLHttpRequest对象:

var request = new XMLHttpRequest();

IE6中的XMLHttpRequest

在以前IE的版本中是使用ActiveX对象代替XMLHttpRequest。

if (window.XMLHttpRequest === undefined){    window.XMLHttpRequest = function(){        try{            //如果可用,则使用ActiveX对象的最新版本            return new ActiveXObject("Msxml2.XMLHttp.6.0");        }        catch(e1){            try{                //否则,回退到较旧的版本                return new ActiveXObject("Msxml2.XMLHttp.3.0");            }            catch(e2){                //否则,抛错                throw new Error("XMLHttpRequest is not supported");            }        }    }}

一个Http请求由4个部分组成:

  • Http请求的方法或“动作”
  • 正在请求的URL
  • 一个可选的请求头集合
  • 一个可选的请求体

一个服务器返回的Http响应包含3部分:

  • 一个数组和文字组成的状态码
  • 一个响应头集合
  • 响应主体

指定请求

创建XMLHttpRequest对象之后,发起Http请求的的下一步是调用XMLHttpRequest对象的open()方法指定这个请求的两个必须部分:方法和URL。

request.open("GET",//一个Http GET请求        "index.action");//URL

如果有请求头的话,请求进错的下个步骤是设置它。

request.setRequestHeader("Content-Type","text/plain");

使用XMLHttpRequest发起Http请求的最后一步是指定可选的请求主体并向服务器发送它。使用send()方法。

request.send(null);

取得响应

XMLHttpRequest对象的属性和方法

  • status和statusText属性以数字和文本的形式返回Http状态码。
  • 使用getResponseHeader()和getAllResponseHeaders()能查询响应头。不能获取cookie。
  • 响应主体可以从responseText属性中得到文本形式的,从responseXML属性中得到Document形式的。

readyState是一个整数,它指定了Http请求的状态。第一列的符号是XMLHttpRequest构造函数定义的常量。

这里写图片描述

每次readyState属性改变都会触发readystatechange事件。

同步响应

XMLHttpRequest支持同步响应。如果把false作为第三个参数传递给open(),那么send()方法将阻塞知道请求完成。这种情况下,不需要使用事件处理程序:一旦send()返回,仅需要检查XMLHttpRequest对象的status和responseText属性。

响应解码

假设服务器使用像“text/plain”、”text/html”或“text/css”这样的MIME类型发送文本响应,然后我们使用XMLHttpRequest对象的responseText属性得到它。

如果服务器发送XML或XHTML文档作为其响应,你能通过responseXML属性获得一个解析形式的XML文档。这个属性的是值是一个Document对象。

如果服务器在“Content-Type”头中包含了错误的“charset”参数,那么XMLHttpRequest将使用错误的编码来解析响应,并且responseText中的字符可能是错的。可以使用XHR2定义打的overrideMineType()方法来解决问题。在低啊用send()之前把类型传递给overrideMimeType(),这个将使XMLHttpRequest忽略“Content-Type”头而使用指定的类型。

request.overrideMimeType("text/plain; charset=utf-8");

编码请求主体

表单的请求

对表单数据使用的编码方案相对简单:每个表单元素的名字和值纸箱普通的URL编码(使用十六进制转义码替换特殊字符),使用等号把编码后的名字和值分开,并使用“&”符号分开名/值对。一个简单表单的编码如下这样:

name1=value1&name2=value2

表单数据编码格式有一个正式的MIME类型

application/x-www/urlencoded

当使用POST方法提交这种顺序的表单数据时,必须设置“Cotent-Type”请求头为这个值。

使用表单编码数据发起一个HTTP POST请求

function postData(url, data, callback){    var request = new XMLHttpRequest();    request.open("POST",url);    request.onreadystatechange = function(){        if (request.readyState === 4 && callback){            callback(request);        }    }    request.setRequestHeader("Content-Type","application/x-www-urlencoded");    //encodeFormData()方法将JavaScript对象编码为表单传递数据的格式    request.send(encodeFormData(data));}

使用表单编码数据发起一个HTTP GET请求

function getData(url, data, callback){    var request = new XMLHttpRequest();    request.open("GET",url+"?"+encodeFormData(data));    request.onreadystatechange = function(){        if (request.readyState === 4 && callback){            callback(request);        }    }    request.send(null);}

JSON编码的请求

作为Web交换格式的JSON已经得到普及。

function postData(url, data, callback){    var request = new XMLHttpRequest();    request.open("POST",url);    request.onreadystatechange = function(){        if (request.readyState === 4 && callback){            callback(request);        }    }    request.setRequestHeader("Content-Type","application/json");    request.send(JSON.stringify(data));}

XML编码的请求

fimctopm postQuery(url,callback){    var request = new XMLHttpRequest();    request.open("POST",url);    request.onreadystatechange = function(){        if (request.readyState === 4 && callback){            callback(request);        }    }    //Create an XML document    var doc = document.implementation.createDocument("","query",null);    var query = doc.documentElement;    var find = doc.createElement("find");    query.appendChild(find);    find.setAttribute("zipcode","value");    find.setAttribute("radius","value");    find.appendChild(dic.createTextNode("text"));    request.send(doc);}

上传文件

HTML表单始终能上传文件,但不能使用XMLHttpRequest API做相同的事情。然后,XHR2 API允许通过send()方法传入File对象来实现上传功能。

没有File()对象的构造函数,脚本能通过获得用户当前选择文件的File对象。在支持File对象的浏览器中,每个<input type=”file”/>元素有一个files属性,他是File对象的类数组对象。

function(){    var elts = document.getElementsByName("input");    for (var i = 0; i < elts.length; i++){        var input = elts[i];        if (input.type != "file") continue;        input.addEventListener("change",function(){            var file = this.files[0];            if (!file) return;            var xhr = new XMLHttpRequest();            xhr.open("POST","url");            xhr.send(file);        }, false);    }}

multipart/form-data请求

当HTML表单同时包含文件上传元素和其他元素时,浏览器不能使用普通的表单编码而必须使用称为“multipart/form-data”的特殊Content-Type来用POST方法提交表单。

XHR2定义了新的FormData API,它容易实现多部分请求主体。首先,使用FormData()构造函数创建FormData对象,然后按需多次调用这个对象的append()方法吧个体“部分”添加到请求中。最后,把FormData对象传递给send()方法。

function postFormData(url, data, callback){    if (typeof FormData === "undefined")        throw new Error("FormData is not implemented");    var request = new XMLHttpRequest();    request.open("POST",url);    request.onreadystatechange = function(){        if (request.readyState === 4 && callback){            callback(request);        }    }    var formData = new FormData();    for (var name in data){        if (!data.hasOwnProperty(name))            continue;        if (typeof value === "function")            continue;        formData.append(name,value);    }    request.send(formData);}

HTTP进度事件

在调用send()时,出法单个loadstart事件。当正在加载服务器的响应时,XMLHttpRequest对象会发生progress事件,通常每隔50毫秒左右,所以可以使用这些事件给用户反馈请求事件。如果请求快速完成,它可能不会触发progress事件。当事件完成,会触发load事件。

HTTP请求无法完成有3种情况。如果请求超时,会触发timeout事件。如果请求终止,会触发abort事件。最后,想大多数重定向这样的网络错误会阻止请求完成,当这些情况发生时会触发error事件。

XHR2规范草案指出只要触发load、abort、timeout和error中的一个。浏览器就会触发loadend事件。

progress事件相关联的事件有3个有用的属性

  • loaded属性是目前传输的字节数值
  • total属性是自“Content-Lenght”头传输的数据的整体长度(单位是字节),如果不知道内容长度则为0
  • lengthComputable属性为true表示知道内容长度,否则为false
request.onprogress = function(e){    if (e.lengthComputable)        progress.innerHTML = Math.round(100*e.loaded/e.total) + "% Complete";}

终止请求和超时

可以通过调用XMLHTTPRequest对象的abort()方法来取消正在进行的HTTP请求。调用abort()方法会触发对象的abort事件。

XHR2定义了timeout属性来指定请求终止后的毫秒数,也定义了timeout事件用于当超时时发生时触发。

如果浏览器没实现timeout,我们就自己来实现。

function timeGetText(url,timeout,callback){    var request = new XMLHttpRequest();    var timeout = false;    var timer = setTimeout(function(){        timeout = true;        request.abort();    }, timeout);    request.open("GET", url);    request.onreadystatechange = function(){        if (request.readyState !== 4)            return;        if (timeout)            return;        clearTimeout(timer);        if (request.status === 200)            callback(request);    }    request.send(null);}

借助<script>发送HTTP请求:JSONP

<script>可以作为一种Ajax传输机制:只需设置<script>元素的src属性,然后浏览器就会发送一个HTTP请求以下载src属性所指向的URL。

当通过<script>元素调用数据时,响应内容必须用JavaScript函数名和圆括号包裹起来。

handleResponse({a:"a",b:"b"});
function getJSONP(url, callback){    var cbnum = "cb" + getJSONP.couter++;    var cbname = "getJSONP." + cbnum;    if (url.indexOf("?") === -1)        url += "?jsonp=" + cbname;    else        url += "&jsonp=" + cbname;    var script = document.createElement("script");    getJSONP[cbnum] = function(response){        try{            callback(response);        }        finally{            delete getJSONP[cbnum];            script.parentNode.removeChild(script);        }    }    script.src = url;    document.body.appendChild(script);}getJSONP.couter = 0;

基于服务器端推送事件的Comet技术

EventSource对象,简化了Comet应用程序的编写可以传递一个URL给EventSource()构造函数,然后在返回的实例上监听消息事件。

var ticker = new EventSource("url");ticker.onmessage = function(e){    var type = e.type;    //服务器发送过来的数据在e.data中    var data = e.data;}
阅读全文
0 0
原创粉丝点击