概述
對于web應用程式:使用者浏覽器發送請求.伺服器接收并處理請求,然後傳回結果,往往傳回就是字元串(HTML),浏覽器将字元串(HTML),渲染并顯示浏覽器上·
Ajax和Form表單送出資料的的好處有以下兩種:
Form表單送出資料的時候,呈現在頁面上是重新整理整個頁面·
Ajax送出資料的時候,隻把有用的資料給送出過去,其餘的不變·
1:傳統的web應用
一個簡單操作需要重新加載全局資料
2:AJAX
ajax,Asynchronous JavaScript and XML(異步的JavaScript和XML),一種建立互動式網頁應用的網頁開發技術方案·
· 異步的JavaScript:
使用[JavaScript語言]以及相關[浏覽器提供類庫]的功能向服務端發送請求,當服務端處理請求之後,[自動執行某個JavaSript的回調函數]·
PS:以上請求和響應的整個過程是(偷偷)進行的,頁面上無任何感覺·
·XML
XML是一種标記語言,是Ajax在和背景互動時傳輸資料的格式之一·
利用AJAX可以做:
1丶注冊時,輸入使用者名自動檢測使用者是否已經存在·
2丶登入時,提示使用者名密碼錯誤·
3丶删除資料行時,将行ID發送到背景,背景在資料庫中删除,資料庫删除成功後,在頁面DOM中将資料行業删除·
"僞"AJAX
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div>
<p>請輸入要加載的位址:<span id="currentTime"></span></p>
<p>
<input id="url" type="text" />
<input type="button" value="重新整理" onclick="LoadPage();">
</p>
</div>
<div>
<h3>加載頁面位置:</h3>
<iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe>
</div>
<script type="text/javascript">
//頁面加載完成之後自動執行這個函數
window.onload= function(){
var myDate = new Date(); //建立一個時間對象 = 擷取目前時間
document.getElementById('currentTime').innerText = myDate.getTime();
//把它的時間擷取到
};
//LoadPage是由重新整理觸發的,一點重新整理就執行LoadPage函數
function LoadPage(){
var targetUrl = document.getElementById('url').value; //輸入什麼值就擷取都什麼值
document.getElementById("iframePosition").src = targetUrl;
//輸入什麼URL“iframePosition”标簽的src就等于什麼
}
</script>
</body>
</html>
原生AJAX
ajax主要就是使用[XmlHttpRequest]對象未完成請求的操作,該對象在主浏覽器中均存在(除早期的IE),AJAX首次出現IE5.5存在(Active控件)·
1丶XmlHttpRequest對象介紹
xmlHttpRequest對象的主要方法:
1·void open(String metthod, String url, Boolen async)
#用于建立請求
#參數:
method:請求方式(字元串類型),如:POST,GET,DELETE...
url:要請求的位址(字元串類型)
async:是否異步(布爾類型)
2·viod send(String body)
#用于發送請求
#參數
body:要發送的資料(字元串類型)
3·void setRequestHeader(String header,String value)
#用于設定請求同
#參數:
header:請求同的key(字元串類型)
value:請求頭的value(字元串的類型)
4· Strig getAllResponseHerders()
#擷取所有響應頭
#傳回值:
響應頭資料(字元串類型)
5·String getResponseHeader(String header)
#擷取響應頭中指定header的值
#參數:
header:響應頭的key(字元串類型)
#傳回值:
響應頭中指定的header對應的值
6· void abort()
#終止請求
XmlHttpRequest對象的主要屬性 :
(數字類型)
1. Number readyState
狀态值(整數)
詳細:
0-未初始化,尚未調用open()方法;
1-啟動,調用了open()方法,未調用send()方法;
2-發送,已經調用了send()方法,未接收到響應;
3-接收,已經接收到部分響應資料;
4-完成,已經接收到全部響應資料;
2. Function onreadystatechange
當readyState的值改變時自動觸發執行其對應的函數(回調函數)
3. String responseText
伺服器傳回的資料(字元串類型)
4. XmlDocument responseXML
伺服器傳回的資料(Xml對象)
5. Number states
狀态碼(整數),如:200、404... 500(伺服器錯誤) 404(沒找到) 200系列的(都屬正常)
6. String statesText
狀态文本(字元串),如:OK、NotFound...
2丶跨浏覽器支援
·XmlHttpRequest
IE7+,Firefox,Chrome,Opera,etc·
·ActiveXObject("Microsoft.XMLHTTP")
IE6,IE5
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>XMLHttpRequest - Ajax請求</h1>
<input type="button" onclick="XmlGetRequest();" value="Get發送請求" />
<input type="button" onclick="XmlPostRequest();" value="Post發送請求" />
<script src="/statics/jquery-1.12.4.js"></script>
<script type="text/javascript">
//建立xhr對象
function GetXHR(){
var xhr = null; //預設xhr = null
if(XMLHttpRequest){ //如果(XMLHttpRequest)為真的話表示目前浏覽器有這個東西
xhr = new XMLHttpRequest(); //通過 new建立一個對象
}else{ //否則的話
xhr = newActiveXobject("Miacosoft.XMLHttp"); //就用ActiveXobject這個插件用xhr去建立
}
return xhr; //這樣的話xhr就可以相容這個浏覽器了,相容浏覽器它給的傳回值
} //就是一個可以發送那麼一個ajax請求的的對象,拿到這個對象我們就可以發請求了
function XhrPostRequest(){
ver xhr = GetXHR(); //擷取對象
//定義回調函數
xhr.obnreadystatechange = function(){ //執行成功之後的一個回調,這次請求執行成功了就會自動執行函數,
//隻是定義了,完成之後才會執行,沒完成就不會執行這個函數
if(xhr.readyState == 4){ //readyStat == 4 表示已經接收完畢
//已經接收到全部響應資料,執行以下操作
var data = xhr.responseText; //傳回的文本内容
console.log(data); //列印
}
};
//指定連接配接方式和位址----檔案夾
xhr.open("POST","/test/",true); //打開這個連結,以post方式發送URL:/test/
//設定請求頭
xhr.setRequestHeade("Content-Type","application/x-www-form-urlencong="utf-8");
//發送請求
xhr.send(); //發送
}
}
</script>
</body>
</html>
JQuery Ajax
jQuery其實就是一個Javascript的類庫,其将複雜的功能做了上層封裝,使得開發者可以在基礎上寫更少的代碼實作更多的功能·
· jQuery不是生産者,而是大自然的搬運工·
· jQuery Ajax本質 XML HttpRequest 或 ActiveXobject
注:2.+版本不再支援IE9以下的浏覽器
$.get({
url:"位址",
data:"{"k1":"v1"}", //傳輸的資料
dataType:"json", // 這樣寫的話就會在内部執行字元串轉成字典
success:function(xx){ //執行成功之後,就會自動執行個xx
obj = JSON.parse(xx) //把字元串轉換成字典
}
})
$.getjson() //寫着一句,相當于dataType在内部設定成json了
$.getscript() //寫着一句,相當于dataType在内部設定成script了
$.post({
url:"位址",
data:"{"k1":"v1"}", //傳輸的資料
success:function(xx){ //執行成功之後,就會自動執行個xx
}
})
$.ajax({
url:"位址",
type:"post", //表示要發post請求
.....
})
//本質上get和post都會調用ajax方法
jQuery.get(...)
所有參數:
url:待載入頁面的url位址
data:待發送 key、value參數
success:載入成功時回調函數
dataType:傳回内容格式,xml,json,script,text,html
jQuery.post(....)
所有參數:
url:帶載入頁面的url位址
data:待發送 key/value 參數
success:載入成功時回調函數
dataType:傳回内容格式,xml,json,script,text,html
jQyery.getScript(....)
所有參數:
url;待載入頁面的url位址
data:待發送key/value參數
success:載入成功時回調函數
jQuery.ajax(....)
部分參數:
url:請求位址
type:請求方式,GET丶POST(1.9.0之後用method)
headers:請求頭
data:要發送的資料
contentType:即将發送資訊至伺服器的内容編碼類型 (預設:"application/x-www-form-urlencoded;charset = utf-8")
async:是否 異步
timeout:設定請求逾時時間(毫秒)
bempletet:完成之後執行回調函數(全局)
su發送請求前執行回調函數(全局) coccess:成功之後執行的回調函數(全局)
error:失敗之後執行的回調函數(全局)
accepts:通過請求頭發送給伺服器,告訴伺服器目前用戶端可接受的資料類型
dataType:将伺服器端傳回的資料轉換成指定類型
“xml”:将伺服器端傳回的内容轉換成xml格式
“text”:将伺服器端傳回的内容轉換成普通文本格式
“html”:将伺服器端傳回的内容換換成普通文本格式,在插入DOM中時,如果包含Jvascript标簽,則會嘗試去執行
“script”:嘗試将傳回值當做javascript去執行,然後再将伺服器端傳回的内容轉換成普通文本格式
“json”:将伺服器端傳回的内容轉換成相應的Javascript對象
‘jsonp’:JSONP格式
使用 JSONP 形式調用函數時,如"myurl?callback = ?" jQuery 将自動替換 ? 為正确的函數名, 以執行回調函數
如果不指定,jQuery 将自動根據HTTP包MIME資訊傳回相應類型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string
converters: 轉換器,将伺服器端的内容根據指定的dataType轉換類型,并傳值給success回調函數
$.ajax({
accepts: {
mycustomtype: 'application/x-some-custom-type'
},
// Expect a `mycustomtype` back from server
dataType: 'mycustomtype'
// Instructions for how to deserialize a `mycustomtype`
converters: {
'text mycustomtype': function(result) {
// Do Stuff
return newresult;
}
},
});
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="button" onclick="XmlSendRequest();" value='Ajax請求' />
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'GET',
dataType: 'text',
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>
跨域AJAX
由于浏覽器存在同源政策機制,同源政策阻止從一個源加載的文檔或腳本擷取或設定另一個源加載的文檔屬性·
特别的:由于同源政策是 浏覽器的限制,所有請求的發送和響應是可以進行,隻不過浏覽器不接受罷了·
浏覽器同源政策并不是對所有的請求均制約:
·制約:XMLHttpRequese
·不叼:img,iframe,script燈具有src屬性的标簽
跨域,跨域名通路,如:http://www.c1.com 域名向 http://www.c2.com域名發送請求。
1丶JSONP實作跨域請求
JSONP(JSONP - JSON with Padding是JSON的一種 “使用模式”),利用 script标簽src屬性(浏覽 器允許script标簽跨域)
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="button" onclick="Jsonp1();" value='送出'/>
</p>
<p>
<input type="button" onclick="Jsonp2();" value='送出'/>
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function Jsonp1(){
var tag = document.createElement('script');
tag.src = "http://c2.com:8000/test/";
document.head.appendChild(tag);
document.head.removeChild(tag);
}
function Jsonp2(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'GET',
dataType: 'JSONP',
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>
2丶CORS
随着技術的發展,現在的浏覽器可以支援主動設定進而允許跨域請求,既:跨域走遠共享(CORS,Cross-Origin Resource Sharing),基本質是設定響應頭,使得浏覽器允許跨域請求·
*簡單請求OR非簡單請求
條件:
1丶請求方式:HEAD,GET,POST
2丶請求頭資訊:
Accept
Accept - Language
Content - Language
Last - Event - ID
Content - Type 對應的值是以下三個中的任意一個
application/x- www - form - urlencoded
multipart/form - data
text/plain
注意:同時滿足以上兩個條件時,則 是簡單請求,否則為複雜請求
*簡單請求和非簡單請求的差別?
1·簡單請求:一次請求
2·非簡單請求:兩次請求,在發送資料之前會會先發一次請求用于做“預檢”,隻有“預檢”通過後才再發送一次請求用于資料傳輸·
*關于“預檢”*
請求方式:OPTIONS
"預檢":其實做檢查,檢查如果通過則允許傳輸資料,檢查不通過則不再發送真正想要的發送的消息·
如何“預檢”:
如果複雜請求是PUT等請求,則服務端需要設定允許某請求,否則“預檢”不通過
Access-Control-Request-Method
如果複雜請求設定了請求頭,則服務端需要設定允許某請求頭,否則“預檢”不通過
基于cors實作AJAX請求:
1丶支援跨域,簡單請求
伺服器設定響應頭:Access-Control-Allow-Origin = “域名”或“*”

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="submit" onclick="XmlSendRequest();" />
</p>
<p>
<input type="submit" onclick="JqSendRequest();" />
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
}
};
xhr.open('GET', "http://c2.com:8000/test/", true);
xhr.send();
}
function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'GET',
dataType: 'text',
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>
HTML

import tornado.web
import tornado.ioloop
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.write('{"status": true, "data": "seven"}')
Tornado
2丶支援跨域,複雜請求
由于複雜請求時,首先會發送“預檢”請求,如果‘預檢’成功,則發送真實資料·
·‘預檢’請求時,允許請求方則 需要伺服器 設定響應頭:Access-Control-Request-Method
·‘預檢’請求時,允許請求頭則需要伺服器設定響應頭;Access-Control-Request-Headers
·‘預檢’緩存時間,伺服器設定響應頭:Access-Control-Max-Age
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="submit" onclick="XmlSendRequest();" />
</p>
<p>
<input type="submit" onclick="JqSendRequest();" />
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
}
};
xhr.open('PUT', "http://c2.com:8000/test/", true);
xhr.setRequestHeader('k1', 'v1');
xhr.send();
}
function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>
import tornado.web
import tornado.ioloop
class MainHandler(tornado.web.RequestHandler):
def put(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.write('{"status": true, "data": "seven"}')
def options(self, *args, **kwargs):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Headers', "k1,k2")
self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
self.set_header('Access-Control-Max-Age', 10)
3丶跨域擷取響應頭
預設擷取到的所有響應頭隻有基本資訊,如果想要擷取自定義的響應頭,則需要伺服器端設定Access-Contorl-Expose-Headers

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="submit" onclick="XmlSendRequest();" />
</p>
<p>
<input type="submit" onclick="JqSendRequest();" />
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
// 擷取響應頭
console.log(xhr.getAllResponseHeaders());
}
};
xhr.open('PUT', "http://c2.com:8000/test/", true);
xhr.setRequestHeader('k1', 'v1');
xhr.send();
}
function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
success: function(data, statusText, xmlHttpRequest){
console.log(data);
// 擷取響應頭
console.log(xmlHttpRequest.getAllResponseHeaders());
}
})
}
</script>
</body>
</html>

class MainHandler(tornado.web.RequestHandler):
def put(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('xxoo', "seven")
self.set_header('bili', "daobidao")
self.set_header('Access-Control-Expose-Headers', "xxoo,bili")
self.write('{"status": true, "data": "seven"}')
def options(self, *args, **kwargs):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Headers', "k1,k2")
self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
self.set_header('Access-Control-Max-Age', 10)
4·跨域傳輸cookie
在跨域請求中,預設情況下,HTTP Authentication資訊,Cookie頭以及使用者的SSL證書無論在預檢請求中或是在實際請求都是不會被發送·
如果想要發送:
·浏覽器端:XMLHttpRequest的withCredentials為true
·伺服器端:Access-Control-Allow-Credentials為true
·注意:伺服器響應的Access-Control-Allow-Origin 不能是通配符 *

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="submit" onclick="XmlSendRequest();" />
</p>
<p>
<input type="submit" onclick="JqSendRequest();" />
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function XmlSendRequest(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
var result = xhr.responseText;
console.log(result);
}
};
xhr.withCredentials = true;
xhr.open('PUT', "http://c2.com:8000/test/", true);
xhr.setRequestHeader('k1', 'v1');
xhr.send();
}
function JqSendRequest(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'PUT',
dataType: 'text',
headers: {'k1': 'v1'},
xhrFields:{withCredentials: true},
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>

import tornado.web
import tornado.inloop
class MainHandler(tornado.web.RequestHandler):
def put(self):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Credentials', "true")
self.set_header('xxoo', "seven")
self.set_header('bili', "daobidao")
self.set_header('Access-Control-Expose-Headers', "xxoo,bili")
self.set_cookie('kkkkk', 'vvvvv');
self.write('{"status": true, "data": "seven"}')
def options(self, *args, **kwargs):
self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
self.set_header('Access-Control-Allow-Headers', "k1,k2")
self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
self.set_header('Access-Control-Max-Age', 10)