腳本化HTTP
下面將會用js代碼操縱HTTP
下面將會說明在沒有致使web瀏覽器從新加載任何窗口或者窗體的狀況下,腳本實現web瀏覽器和服務器之間的通訊。
ajax:爲一種找早起避免頁面重載而動態更新頁面的方式,不過如今是直接數據驅動,或者相似於vue的單頁應用
comet:這個和ajax正好相反,爲推送消息到web瀏覽器端php
ps;ajax和comet都爲一個美國的洗滌日用品牌,╮(╯▽╰)╭html
img元素有一個src屬性,當腳本設置img元素的src屬性,且把信息做爲圖片的url的查詢字符串部分,即能把通過編碼的信息椽筆給web服務器,web服務器實際上必須返回一個圖片做爲結果。
事實上,使用一個空的js腳本也可完成此操做
一個百度統計的js腳本以下vue
(function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d2539dae35b4dcf0e7814c110ecefa9f"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })();
分析,一個採用es5編寫的一個閉包,動態加載一個script標籤,向https://hm.baidu.com/hm.js?d2539dae35b4dcf0e7814c110ece發送一個get請求,而且查詢的字符串爲?後面的參數,服務器只須要統計?後面的get請求數目,便可完成一次次的統計任務。用戶的頁面停留,直接計算兩次加載的時間差便可。數據庫完成統計便可。一個最簡單的頁面統計完成。java
一個淘汰的標籤。
下面是舊的ajax方式
使用iframe完成一次ajax,腳本先把要發送給web服務器的信息編碼到url中,服務器在動態的建立一個html文檔,將其內容返回給web,在iframe中顯示,這種方式受道同源的限制。
上方的方式以及放棄。web
經過script元素的src屬性設置url發起http get請求,即一種基於script的ajax傳輸,服務器使用json編碼,執行腳本的時候,將其轉碼,這種的ajax同時也稱爲jsonp
即這種的跨域能夠不受到同源的限制ajax
ajax中的x爲xml爲一種可選的通訊方式,也可使用JSON完成通訊。chrome
一些更多的通訊協議,包括rpc(遠程過程調用)容許運行於一臺計算機的程序調用另外一臺計算機程序的子程序。若是面向對象編程,則遠程過程調用爲遠程調用,遠程方法調用。數據庫
一種設計模式,有兩種,一種是觀察者模式,一種是發佈訂閱模式,
即,消息推送使用的是發佈/訂閱事件系統編程
意圖:定義對象間的一對多的依賴關係,當一個對象狀態發生改變時,全部依賴它的對象都獲得通知,並進行更新
解決:一個對象狀態給其餘對象通知的問題,
舉例應用:有個天氣中心的目標A,專門監聽天氣的變化,而有個顯示天氣的觀察者B,B把本身註冊到A裏,當A觸發天氣變化的時候,調度B更新方法,並帶上本身的上下文。
json
訂閱者把本身想註冊的事件註冊到調度中心,當該事件觸發時,發佈者發佈事件到調度中心,由調度中心統一調度訂閱者註冊到調度中心的處理代碼。
舉例:有個界面實時顯示天氣,它就訂閱天氣事件(註冊到調度中心),當天氣變化時定時獲取數據,做爲發佈者到調度中心,調度中心調度訂閱者的天氣處理程序。
一個爲點對點,一個爲中間有一個過渡的,僅此而已。
ps 有一本書js的設計模式,推薦看看 http://shop.oreilly.com/product/0636920025832/ReviewSubmit.do?sortby=publicationDate?pageId=0636920025832.IP 以及 https://addyosmani.com/resources/essentialjsdesignpatterns/book/
購買 https://www.amazon.com/_/dp/1449331815?tag=oreilly20-20
很想知道有木有中文版的。吐槽 28美圓,合計120多元,書怎麼那麼貴呢。好貴,建議註冊一下
瀏覽器在CMLHttpRequest類上定義了其HTTP 的API 這個類的每一個實例都表示一個獨立請求/響應對。而且這個對象屬性和方法容許指定請求細節和提取響應數據。
同java相似,使用這個api的第一件事實例化XMLHttpRequest對象
ps:能重用已存在的XMLHttpRequest 可是以前的對象將會被掛起
在本地寫js的時候,必須搭建一個服務器其AJAX才能工做
緣由:由於文件的協議爲file而本地的請求的協議爲http,因爲同源策略的影響,致使沒法使用http協議的文件,故本地沒法直接使用ajax
解決方法,chrome的瀏覽器訪問https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb 安裝chrome官方提供的本地測試服務器,用於在本地搭建服務器。
或者,編寫Node.js 使用Express框架,加載Static 模塊,完成本地的靜態服務器搭建。
指定請求使用的是request.open(),此方法將會初始化一個請求從js代碼中調用。
第一個參數指定HTTP方法或動做,字符串不區分大小寫,一般用大寫字母匹配HTTP協議,GET用於常規請求,適用於當URL徹底指定請求資源。當請求對服務器沒有任何反作用以及當服務器的響應可緩存的時候,使用GET。對於POST來講,經常用於HTML表單,它在請求主體中包含額外數據,即表單數據,且這些數據經常儲存到服務器的數據庫中。此請求不會被緩存。
一樣的,還容許其餘的一些請求,例如DELETE,HEAD,OPTIONS,PUT等請求。
第二個參數爲URL,爲請求的主體,相對於文檔的URL,這個文檔包含調用open()的腳本,這個不能跨域,請求必須爲同域的
request.setRequestHeader('Content-type', 'text/plain');
下面將會設置請求頭,上方設置請求頭爲Content-type的內容爲text/plain
有些請求頭因爲瀏覽器的安全問題,被禁止請求,因此有些不能請求。
若是請求一個受到密碼保護的url,此時不須要設置Authorization頭,只須要直接在open的第三四個參數,傳入便可。
因爲get請求不包括主體,則直接send方法便可完成一個包的發送,
在http://1.197.156.53/編寫js以下
// 編寫請求頭GET並完成發送 var request = new XMLHttpRequest(); // 設置請求的類 request.open('GET', 'https://www.baidu.com/'); // 設置請求的連接和方式 request.setRequestHeader('Content-Type', 'text/plain'); // 設置請求頭 request.send(null); // 發送包
跨域請求被攔截。
因爲不是同源,同源被攔截
// 編寫請求頭GET並完成發送 var request = new XMLHttpRequest(); // 設置請求的類 request.open('GET', './index.js'); // 設置請求的連接和方式 request.setRequestHeader('Content-Type', 'text/plain'); // 設置請求頭 request.send(null); // 發送包
完成一次發包操做
HTTP請求的各個部分有指定的順序,請求方法和URL會首先到達,而後接着請求頭,最後請求主體。最後調用send()方法,完成發送。
順序問題:必須先調用open後調用send()才方可。
function postMessage(msg) { var request = new XMLHttpRequest(); // 新請求 request.open('post', '/log.php'); // 用POST向服務器端發送腳本 // 用請求主體發送純文本消息 request.setRequestHeader('Content-Type', 'text.plain;charset=utf-8'); // 請求主體將是純文本 request.send(msg); // 請求完成,咱們將忽略任何響應和任何錯誤 }
即上方定義了一個post請求,完成其發送,等待其服務器響應
send()發送之後將會等待服務器響應,此時將不會阻塞。
在HTTP發送完成請求之後,下一步將會取得響應。
下面編寫函數獲取HTTP響應的onreadystatechange
// 發出一個HTTP GET請求獲取指定的URL的內容 // 當響應成功到達,驗證它是不是純文本 // 若是是,將會把它傳遞給指定的回調函數 function getText(url, callback) { var request = new XMLHttpRequest(); // 建立一個新請求 request.open('GET', url); // 建立一個指定待獲取的url request.onreadystatechange = () => { // 當GRT請求完成之後,觸發該事件,產生回調函數 // 若是請求完成,則它是成功的 if (request.readyState === 4 && request.status === 200){ // 若是下載操做完成,即爲4,而且http狀態碼爲200 var type = request.getResponnseHeader('Content-Type'); // 獲取HTTP頭部信息 if (type.match(/^text/)) //正則匹配,肯定響應爲文本 callback(request.responseText); // 回調函數,將返回的DOM樹,傳遞給回調函數 } }; request.send(null); // 發送 }
注意,該方式爲異步的,send方法不會阻塞其餘操做
因爲其下載的問題,通常異步處理HTTP響應,可是同步也能夠,不過因爲客戶端js爲單線程的,當send()方法阻塞之後,將會致使瀏覽器的ui被凍結,若是鏈接的服務器過慢,將會致使用戶的操做出現問題。
方法直接open使用第三個參數爲false
當服務器響應的爲XML文檔的時候,其返回的值爲document對象,能使用操做節點的方式,對其進行操做
當服務器發送對象或者數組的結構化數據,如JSON,
使用JSON.parse 對結構化數據進行解析
下方書寫一個函數,進行結構化數據的解析
// 發起HTTP GET響應,得到指定的URL內容 // 當響應到達時,把他們解析後的XML Document對象,解析後的JSON對象 // 或者字符串形式傳遞給回調函數 function get(url, callback){ var request = new XMLHttpRequest(); request.open('GET', url); // 指定url request.onreadystatechange = () => { // 監聽器 // 若是請求完成且成功 if (request.readyState === 4 && request.status === 200) { // 得到響應請求 var type = request.getResponseHeader('Content-Type'); // 檢查類型 // 當爲xml的時候 if (type.indexOf('xml') !== -1 && request.responseXML) // 確認是否爲xml calback(request.responseXML); // 回調函數 else if (type === "application/json") // 若是頭部的信息爲JSON callback(JSON.parse(request.responseText)); // 將結果JSON格式解析 else callback(request.responseText); // 若是是字符串響應 } }; request.send(null); // 當即發送請求 }
對兩種數據解析,一種爲JSON格式,一種爲XML格式
ps 不建議使用eval
ps 因爲跨域的問題,只能讀取同源的數據,經過script腳本操縱HTTP腳本並實現加載並執行腳本
script 元素能發起跨域的HTTP請求
能使用request.overrideMimeType可以實現對MIME類型的更改