【温故而知新-Javascript】使用 Ajax

Ajax 是现代Web
应用程序开发之同宗重点工具。它让你会望服务器异步发送和接收数据,然后据此
Javascript 解析。 Ajax 是 Asynchronous JavaScript and XML
(异步JavaScript 与XML)的缩写。

Ajax 核心标准的称呼继承给用来树及发起呼吁的 Javascript
对象:XMLHttpRequest
。这个正式来有限个阶段。所有主流浏览器还实现了第一层,它象征了根基级别之效果。第二层扩展了初期的正儿八经,纳入了附加的轩然大波和部分效来被它更易与
form 元素协作,并且支持部分有关专业。

 

1. Ajax起步

Ajax 的关键在于 XMLHttpRequest
对象,而知晓这目标的方式是圈个例证。下面代码展示了 XMLHttpRequest
对象的主导用法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用XMLHttpRequest对象</title>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
</div>
<div id="target">
    Press a button
</div>

<script type="application/javascript">
    var buttons = document.getElementsByTagName("button");
    for(var i=0; i<buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    //脚本会调用此函数以响应 button 控件的 click 事件
    function  handleButtonPress(e){
        //创建一个新的 XMLHttpRequest 对象
        var httpRequest = new XMLHttpRequest();
        //给 onreadystatechange 事件设置一个事件处理器
        httpRequest.onreadystatechange = handleResponse;
        //使用 open 方法来指定 HTTP 方法和需要请求的 URL (即告诉 httpRequest 对象你想要做的事)
        httpRequest.open("GET", e.target.innerHTML+".html");
        //这里没有向服务器发送任何数据,所以 send 方法无参数可用
        httpRequest.send();
    }

    //处理响应
    //一旦脚本调用了 send 方法,浏览器就会在后台发送请求到服务器。因为请求是在后台处理的,所以Ajax 依靠事件来通知这个请求的进展情况。
    function handleResponse(e){
        //当 onreadystatechange 事件被触发后,浏览器会把一个 Event 对象传递给指定的处理函数,target 属性则会被设为与此事件关联的XMLHttpRequest
        if(e.target.readyState == XMLHttpRequest.DONE && e.target.status == 200){ //请求成功
            document.getElementById("target").innerHTML = e.target.responseText; //显示被请求文档的内容
        }
    }
</script>
</body>
</html>

当有按钮被准下后,示例中的脚本会载入另一个HTML文档,并为它们叫做div元素的内容。其他的文档一共老三只,分别对应button元素上的认证标签:apples.html、lemons.html
和 bananas.html。

此例的展示效果使下图所示:

图片 1

就三只附加的文档非常简单,其中apples.html
如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Apples</title>
    <style>
        img { float:left;padding:2px;margin:5px;border: medium double black;background-color: lightgrey; width: 100px;height: 100px;}
    </style>
</head>
<body>
<p>
    <img src="../imgs/apple.png"/>
    Page for apples.
</p>
</body>
</html>

乘机用户点击各个水果按钮,浏览器会异步执行并取回所请求的文档,而主文档不见面受重新加载。这虽是卓越的
Ajax 行为。

 

2. 使用 Ajax 事件

树立及探讨一个简易的演示之后,可以起来深入摸底 XMLHttpRequest
对象支持的功力,以及如何以求中采用她了。起点就是是第二层标准里定义之那些额外事件:

图片 2

这些事件大多数见面当求的某部平一定时刻接触及接触。 readystatechange 和
progress 这半单事件是殊,它们得以频繁沾发以提供进度更新。

调度这些事件时,浏览器会指向 readystatechange 事件采取正规的 Event
对象,对其他事件则以 ProgressEvent 对象。 ProgressEvent 对象定义了
Event 对象的具有成员,并追加了下图被牵线的这些成员:

图片 3

脚代码展示了怎么以这些事件: 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用XMLHttpRequest定义的一次性事件</title>
    <style>
        table {margin: 10px;border-collapse: collapse; float: left;}
        div{margin: 10px;}
        td,th{padding: 4px;}
    </style>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
</div>
<table id="events" border="1"></table>
<div id="target">
    Press a button
</div>

<script type="application/javascript">
    var buttons = document.getElementsByTagName("button");
    for(var i=0; i<buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    var httpRequest;
    function  handleButtonPress(e){
        clearEventDetails();
        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;

        httpRequest.onerror = handleError;
        httpRequest.onload = handleLoad;;
        httpRequest.onloadend = handleLoadEnd;
        httpRequest.onloadstart = handleLoadStart;;
        httpRequest.onprogress = handleProgress;

        httpRequest.open("GET", e.target.innerHTML+".html");
        httpRequest.send();
    }

    function handleResponse(e){
        displayEventDetails("readystate("+httpRequest.readyState+")")
        if(e.target.readyState == XMLHttpRequest.DONE && e.target.status == 200){
            document.getElementById("target").innerHTML = e.target.responseText;
        }
    }

    function handleError(e){ displayEventDetails("error",e);}
    function handleLoad(e){ displayEventDetails("load",e);}
    function handleLoadEnd(e){ displayEventDetails("loadend",e);}
    function handleLoadStart(e){ displayEventDetails("loadstart",e);}
    function handleProgress(e){ displayEventDetails("progress",e);}

    function clearEventDetails(){
        document.getElementById("events").innerHTML = "<tr><th>Event</th><th>lengthComputable</th><th>loaded</th><th>total</th>";
    }

    function displayEventDetails(eventName,e){
        if(e){
            document.getElementById("events").innerHTML
                    +="<tr><td>"+eventName+"</td><td>"+ e.lengthComputable+"</td><td>"+ e.loaded+"</td><td>"+ e.total+"</td></tr>";
        }else {
            document.getElementById("events").innerHTML += "<tr><td>"+eventName+"</td><td>NA</td><td>NA</td><td>NA</td></tr>";
        }
    }
</script>
</body>
</html>

立是前面示例的一模一样种植变化,为部分事变注册了处理函数,并在一个 table
元素里也处理的每个事件还创造了同等修记下。从生图中可见见 Firefox
浏览器是哪触发这些事件的。

图片 4

3. 处理错误

运用 Ajax 时得注意两类似错误。它们之间的区分源于视角各异。

第一看似错误是由 XMLHttpRequest
对象的角度看底题目:某些因素阻止了请求发送至服务器。例如 DNS
无法解析主机名,连接要被拒,或者URL无效。

其次看似题目是由应用程序的角度看到底问题,而非 XMLHttpRequest
对象。它们发出被要成功发送至服务器,服务器收到请求、进行拍卖并转响应,但拖欠应并无指于你望的内容。例如,如果要的URL
不在,这类似题材即见面时有发生。

产生三种方式得以拍卖这些不当,如下面代码所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>处理Ajax错误</title>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
    <button id="badhost">Bad Host</button>
    <button id="badurl">Bad URL</button>
</div>
<div id="target">Press a button</div>
<div id="errormsg"></div>
<div id="statusmsg"></div>

<script type="application/javascript">
    var buttons = document.getElementsByTagName("button");
    for(var i = 0; i < buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    var httpRequest;

    function handleButtonPress(e){
        clearMessages();
        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        httpRequest.onerror = handleError;
        try{
            switch(e.target.id){
                case "badhost":
                    httpRequest.open("GET","http://www.ycdoitt.com/nopage.html")
                    break;
                case "badurl":
                    httpRequest.open("GET","http://")
                    break;
                default:
                    httpRequest.open("GET", e.target.innerHTML + ".html")
                    break;
            }
            httpRequest.send();
        }catch(error){
            displayErrorMsg("try/catch",error.message+"("+error.name+")")
        }
    }

    function handleError(e){
        displayErrorMsg("Error event",httpRequest.status + httpRequest.statusText);
    }

    function handleResponse(){
        if(httpRequest.readyState == 4){
            var target = document.getElementById("target");
            if(httpRequest.status == 200){
                target.innerHTML = httpRequest.responseText;
            }else{
                document.getElementById("statusmsg").innerHTML
                        = "Status:" + httpRequest.status +" "+ httpRequest.statusText;
            }
        }
    }

    function displayErrorMsg(src,msg){
        document.getElementById("errormsg").innerHTML = src + ": " + msg;
    }

    function clearMessages(){
        document.getElementById("errormsg").innerHTML = "";
        document.getElementById("statusmsg").innerHTML = "";
    }
</script>
</body>
</html>

此例演示结果如下:

图片 5

 

3.1 处理装置错误

需处理的第一看似问题是通往 XMLHttpResquest
对象传递了不当的数量,比如格式不得法的 URL
。它们不过容易有在变基于用户输入的URL
时。为了模仿这仿佛题目,上面文档中生上加一个签 Bad URL
(错误的URL)的button 。按下是按钮会以以下形式调用 open 方法:

 httpRequest.open("GET","http://")

顿时是同种会阻止请求执行的左,而 XMLHttpRequest
对象见面出这好像事件不时抛来一个不当。这便表示需要用相同久 try…catch
语句子来包围设置请求的代码,就比如这样:

       try{
            ...
            httpRequest.open("GET","http://")
            ...
            httpRequest.send();
        }catch(error){
            displayErrorMsg("try/catch",error.message)
        }        

catch
子句子被您产生空子从左被回复。可以挑选提示用户输入一个值,也可回退至默认的URL
,或是简单地丢这个请。 在斯例子中,仅仅调用了 displayErrorMsg
函数来显示错误信息。

 

3.2 处理要错误

第二接近错误有在请都成形,但其余方面出错时。为了模仿这类似题材,在演示中补充加了一个签为
Bad Host (错误主机)的按钮。当是按钮被以下后,就会见调用 open
方法访问一个非可用的 URL:

httpRequest.open("GET","http://www.ycdoitt.com/nopage.html")

此URL 存在个别独问题。第一独问题是主机名不能被 DNS
解析,因此浏览器无法转移服务器连接。这个题材掌握 XMLHttpRequest
对象开始转移请求时才见面变得明白,因此它们会盖稀栽方法产生错误信号。如果你注册了一个
error 事件之监听器,浏览器就是会往而的监听函数发送一个 Event
对象。以下是现身说法中使用的函数:

function handleError(e){
        displayErrorMsg("Error event",httpRequest.status + httpRequest.statusText);
    }

当这好像错误有常,能由 XMLHttpRequest
对象获得何种程度之信息在浏览器,遗憾之凡大多数气象下,会沾的值也
0底 status和空域的 statusText 值。

 第二单问题是URL和转移请求的有着不同的来,在默认情况下立刻是免允的。你平常只能望载入脚本的同源URL发送Ajax请求。浏览器报告是题材时常或许会见弃来
Error
或者触发error事件,不同浏览器的处理方式不尽相同。不同浏览器还见面于不同之时点检查来,这即代表不肯定总是能够看浏览器对平问题突出展示。可以运用跨站资源专业(CORS,Cross-Origin
Resource Sharing)来绕了同源限制。

 

3.3 处理应用程序错误

说到底一像样错误有受要成功完成(从XMLHttpRequest对象的角度看),但从不回到您想只要之数码经常。为了做这类似题目,在点示例中上加一个证实标签为
cucumber 的 button 。按下这按钮会生成类似于 apples、cherries 和
bananas 按钮那样的乞求URL,但是于服务器上无有 cucumber.html 这个文档。

顿时同样进程自己没有不当(因为要都到位),需要根据
status属性来确定来了什么。当呼吁某个存在的文档时,会获取404以此状态码,它的意思是服务器无法找到请求的文档。可以望示例是哪处理200(意思是OK)以外的状态码的:

            if(httpRequest.status == 200){
                target.innerHTML = httpRequest.responseText;
            }else{
                document.getElementById("statusmsg").innerHTML
                        = "Status:" + httpRequest.status +" "+ httpRequest.statusText;
            }

于此例子中,只是简短的来得了status和statusText的价值。而以真的的应用程序里,需要为同等种出因此都产生含义之措施进行复原(比如显示备用内容还是警示用户发问题,具体看呀种更称应用程序)。

 

4. 取得与安装标头

用XMLHttpRequest对象,可以装发送给服务器的伸手标头(Header)和朗诵博服务器响应里之标头。

图片 6

 

4.1 覆盖要的HTTP方法

平凡不需添加或改动Ajax请求里的标头。浏览器知道得发送些什么,服务器也懂如何开展响应。不过,有几乎种植状况不一。第一种植是
X-HTTP-Method-Override 标头。

HTTP标准便给用于在互联网及请与导HTML文档,它定义了无数法。大多数丁还晓得GET和POST,因为她的使用最广泛。不过还在任何组成部分道(包括PUT和DELETE),这些HTTP方法用来被于服务器请求的URL赋予意义,而且这种用法正在呈现上升趋势。举个例子,假如想翻某条用户记录,可以老成这样一个央:

httpRequest.open("GET","http://myserver/records/freeman/adam");

 这里才展示了HTTP方法和要的URL。要如之请能顺畅工作,服务器端必须由应用程序能掌握这个请,并拿它们生成成一截合适的数额以发送回服务器。如果想去数据,可以这么写:

httpRequest.open("DELETE","http://myserver/records/freeman/adam");

此的关键在于通过HTTP方法表达有你想叫服务器做啊,而非是管其之所以某种方式编码进URL。

因为这种方法以HTTP方法的题目在:许多主流的Web技术就支持GET和POST,而且多防火墙只同意GET和POST请求通过。有同种惯用的做法得以避开之界定,就是使
X-HTTP-Method-Override标头来指定想如果利用的HTTP方法,但花样上市在殡葬一个POST请求。代码演示如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置一个请求标头</title>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
</div>
<div id="target">Press a button</div>

<script>
    var buttons = document.getElementsByTagName("button");
    for(var i = 0; i < buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    var httpRequest;
    function handleButtonPress(e){
        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        httpRequest.open("GET", e.target.innerHTML+".html");
        httpRequest.setRequestHeader("X-HTTP-Method-Override","DELETE");
        httpRequest.send();
    }

    function handleError(e){
        displayErrorMsg("Error event",httpRequest.status+httpRequest.statusText);
    }

    function handleResponse(){
        if(httpRequest.readyState == 4 && httpRequest.status == 200){
            document.getElementById("target").innerHTML = httpRequest.responseText;
        }
    }
</script>
</body>
</html>

于这事例中,有利用XMLHttpRequest对象上之setRequestHeader方法来表明想让这个要以HTTP
DELETE方法的样式进行处理。请留意自己当调用open方法之后才装了此标头。如果准备以open方法之前使用setRequestHeader方法,XMLHttpRequest对象就会见废弃来一个荒谬。

PS:覆盖HTTP需要服务器端的Web应用程序框架能明白X-HTTP-Method-Override这个规矩,并且你的劳务器端应用程序要安装成能招来与了解那些用之比少之HTTP方法。

 

4.2 禁用内容缓存

第二只好长到Ajax请求上的发出因此标头是Cache-Control,它当编排和调剂脚本时尤其有因此。一些浏览器会缓存通过Ajax请求所得到的情节,在浏览会话中勿见面再度请其。对以前头的例证而言,意味着
apples.html、cherries.html和bananas.html
上之反无会见立马反映至浏览器被。下面代码展示了足以什么设置标头来避免这一点:

        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        httpRequest.open("GET", e.target.innerHTML+".html");
        httpRequest.setRequestHeader("Cache-Control","no-cache");
        httpRequest.send();

安标头的方法跟事先的事例一样,但这次使用的标头是
Cache-Control,而思要之值是
no-cache。放置这长达告词后,如果经过Ajax请求的始末发生了改变,就会在产同样次于呼吁文档时体现出。

 

4.3 读取响应标头

可以通过 getResponseHeader 和 getAllResponseHeaders
方法来读取服务器响应某个Ajax请求时发送的HTTP标头。在多数景下,你免需关爱标头里产生啊,因为其是浏览器和服务器之间交互事务之一对。下面代码展示了何等以这个特性:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta content="width=device-width,user-scalable=no" name="viewport" />
    <meta name="author" content="叶超Luka" />
    <meta name="description" content="A simple example" />
    <title>读取响应标头</title>
    <link href="../img/ycdoit.ico" type="image/x-icon" rel="shortcut icon" />
    <style>
        #allheaders,#ctheader{border: medium solid black;padding: 2px;margin: 2px;}
    </style>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
</div>
<div id="ctheader"></div>
<div id="allheaders"></div>
<div id="target">Press a button</div>

<script>
    var buttons = document.getElementsByTagName("button");
    for(var i = 0; i < buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    var httpRequest;
    function handleButtonPress(e){
        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        httpRequest.open("GET", e.target.innerHTML+".html");
        httpRequest.setRequestHeader("Cache-Control","no-cache");
        httpRequest.send();
    }

    function handleResponse(){
        if(httpRequest.readyState==2){
            document.getElementById("allheaders").innerHTML = httpRequest.getAllResponseHeaders();
            document.getElementById("ctheader").innerHTML = httpRequest.getResponseHeader("Content-Type");
        }else if(httpRequest.readyState == 4 && httpRequest.status == 200){
            document.getElementById("target").innerHTML = httpRequest.responseText;
        }
    }
</script>
</body>
</html>

意义图如下:

图片 7

冲此图可以看出开发服务器在周转的Web服务器软件是 IntelliJ IDEA
15.0.4,最后修改 apples.html 文档的年华是8月17日。

 

5. 扭转跨源Ajax请求

默认情况下,浏览器限制脚本只能于其所属文档的发源外生成Ajax请求。而自由URL中之商谈、主机名和端口号组成。这即象征当从http://titan
载入了一个文档后,文档内含的本子通常无法转移对 http://titan:8080
的求,因为第二独URL的捧口号是不同之,所以处在文档来源外。从一个源于及另外一个出自之Ajax请求于称之为跨源请求(cross-origin
request)。

PS:这同一策略的目的是跌跨站脚论攻击(cross-site
scripting,简称CSS)的风险,即诱导浏览器(或用户)执行恶意脚本。

其一政策的题目在她一刀切地禁止了跨源请求。幸好,跨源资源共享(Cross-Origin
Resource Sharing,CORS)规范提供了一致栽合法的法门来变化跨源请求。

用作备选,下面代码展示了一个HTML文档,它含有的脚本会尝试生成跨源请求:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>尝试生成跨源请求的脚本</title>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
</div>
<div id="target">Press a button</div>

<script>
    var buttons = document.getElementsByTagName("button");
    for(var i = 0; i < buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    var httpRequest;

    function handleButtonPress(e){
        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        httpRequest.open("GET","http://127.0.0.1:8080/"+ e.target.innerHTML);
        httpRequest.send();
    }

    function handleResponse(){
        if(httpRequest.readyState == 4 && httpRequest.status == 200){
            document.getElementById("target").innerHTML = httpRequest.responseText;
        }
    }
</script>
</body>
</html>

以此事例中之本子扩展了用户所按照按钮的内容,把她附加到 http://127.0.0.1:8080/
上,然后尝试生成Ajax请求(如 http://127.0.0.1:8080/apples)。这里会从
http://localhost:63342/HTML5/ajax/ajax-06.html 载入此文档,这便表示脚本正在准备生成一个跨源请求。

剧本尝试连接的服务器运行的凡 Node.js。代码如下,把它保存于了一个誉为也
fruitselector.js 的文本里:

var http = require('http');
http.createServer(function (req,res){
    console.log("[200] "+req.method+" to "+req.url);
    res.writeHead(200,"OK",{
        "Content-Type":"text/html"
        });
    res.write('<html><head><title>Fruit Total</title></head><body>');
    res.write('<p>');
    res.write('You selectd '+req.url.substring(1));
    res.write('</p></body></html>');
    res.end();
}).listen(8080);

立马是一个非常简单的服务器:它根据客户端请求的URL生成一有点段HTML文档。距离的话,如果客户端请求了 http://127.0.0.1:8080/apples
,那么客户端就会见扭转并回到下列HTML文档:

<html><head><title>Fruit Total</title></head><body><p>You selectd apples</p></body></html>

仍现行以此法,show-ajax-css.html
里之本子无法从服务器获取她想要之数。试运作,反映问题如下图所示:

图片 8

为此,解决办法是吗服务器返回浏览器的响应信息上加一个标头,代码如下所示:

var http = require('http');
http.createServer(function (req,res){
    console.log("[200] "+req.method+" to "+req.url);
    res.writeHead(200,"OK",{
        "Content-Type":"text/html",
        "Access-Control-Allow-Origin":"http://localhost:63342"
        });
    res.write('<html><head><title>Fruit Total</title></head><body>');
    res.write('<p>');
    res.write('You selectd '+req.url.substring(1));
    res.write('</p></body></html>');
    res.end();
}).listen(8080);

Access-Control-Allow-Origin
标头指定了某来源应该于允许对这文档生成跨源请求。如果标头里指定的发源当前文档的发源匹配,浏览器就会见加载与拍卖该应所蕴含的数额。

PS:支持CORS要求浏览器必须于联络服务器和沾响应标头之后以跨源安全策略,这即代表就是响应因为缺乏必要之标头或指定了不同的地段而给废除,请求也曾被发送了了。这种方法同没兑现CORS的浏览器非常例外,后者才见面简单的阻挠请求,不会见失掉联系服务器。

为服务器响应添加这个标头之后,show-ajax-css.html
文档中之台本就能呼吁和收取来在服务器的数据了,如下图所示:

图片 9

 

5.1 使用 Origin 请求标头

作CORS的均等有,浏览器会为要加加一个
Origin标头以注明当前文档的源于。可以由此她来再次活地安装
Access-Control-Allow-Origin 标头的价,代码如下所示:

var http = require('http');
http.createServer(function (req,res){
    console.log("[200] "+req.method+" to "+req.url);

    res.statusCode = 200;
    res.setHeader("Content-Type","text/html");

    var origin = req.headers["origin"];
    if(origin.indexOf("localhost:63342") > -1){
        res.setHeader("Access-Control-Allow-Origin",origin)
    }

    res.write('<html><head><title>Fruit Total</title></head><body>');
    res.write('<p>');
    res.write('You selectd '+req.url.substring(1));
    res.write('</p></body></html>');
    res.end();
}).listen(8080);

此地修改了劳务器端的本子,让它们只以呼吁包含Origin标头并且值里来 localhost:63342
时才装 Access-Control-Allow-Origin
响应标头。这是一模一样种植很简短的请来源检查办法,但得因具体项目之上下文环境来调整这种措施,使其再精确。

PS:还好吧 Access-Control-Allow-Origin
标头设置成一个星号(*),意思是容其他来源的跨源请求。使用是设置前应该密切考虑这样做的安全隐患。

 

5.2 高级CORS功能

CORS规范定义了广大格外的标头,可用以精细化控制跨域请求,包括限制请求能以的HTTP方法。这些高级功能要开展相同次于优先请求(preflight
request),即浏览器先往服务器发送一个呼吁来规定出什么限制,然后还发送请求来获取数据本身。

 

6. 搁浅请求

XMLHttpRequest 对象定义了一个可中止请求的艺术,如下图所示:

图片 10

为了演示这个作用,修改 fruitselector.js 这段 Node.js
脚本来引入一个2秒延,代码如下所示:

var http = require('http');
http.createServer(function (req,res){
    console.log("[200] "+req.method+" to "+req.url);

    res.statusCode = 200;
    res.setHeader("Content-Type","text/html");

    setTimeout(function(){        
    var origin = req.headers["origin"];
    if(origin.indexOf("localhost:63342") > -1){
        res.setHeader("Access-Control-Allow-Origin",origin)
    }    
    res.write('<html><head><title>Fruit Total</title></head><body>');
    res.write('<p>');
    res.write('You selectd '+req.url.substring(1));
    res.write('</p></body></html>');
    res.end();
    },2000);


}).listen(8080);

当服务器收到到一个央,它见面优先勾勒副初始的应标头,暂停3秒钟后再也形成所有响应。下面代码展示了何等当浏览器上运用
XMLHttpRequest 的间歇功能:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>中止请求</title>
</head>
<body>
<div>
    <button>apples</button>
    <button>bananas</button>
    <button>lemons</button>
</div>
<div>
    <button id="abortbutton">Abort</button>
</div>
<div id="target">Press a button</div>

<script>
    var buttons = document.getElementsByTagName("button");
    for(var i = 0; i < buttons.length; i++){
        buttons[i].onclick = handleButtonPress;
    }

    var httpRequest;

    function handleButtonPress(e){
        if(e.target.id == "abortbutton"){
            httpRequest.abort();
        }else {
            httpRequest = new XMLHttpRequest();
            httpRequest.onreadystatechange = handleResponse;
            httpRequest.onabort = handleAbort;
            httpRequest.open("GET","http://127.0.0.1:8080/"+ e.target.innerHTML);
            httpRequest.send();
            document.getElementById("target").innerHTML = "Request Started";
        }
    }

    function handleResponse(){
        if(httpRequest.readyState == 4 && httpRequest.status == 200){
            document.getElementById("target").innerHTML = httpRequest.responseText;
        }
    }

    function handleAbort(){
        document.getElementById("target").innerHTML = "Request Aborted";
    }
</script>
</body>
</html>

这边叫文档添加了一个Abort(中止按钮),它经过调用 XMLHttpRequest
对象及之abort方法来刹车进行中的要。因为以劳务器端引入了扳平截延迟,所以发生丰富的时刻来推行其。

XMLHttpRequest 通过 abort 事件和 readystatechange
事件给出暂停信号。在这个例子中,响应了 abort
事件,并创新了id为target的div元素中之内容,以此表明要都为中断。效果图如下:

图片 11

 

来源:《HTML5尊贵指南》(《The Definitive Guide to
HTML5》)

相关文章