指令碼化HTTP 取得響應 指定請求

xiaoxiaoming發表於2018-08-15

指令碼化HTTP 下面將會用js程式碼操縱HTTP 下面將會說明在沒有導致web瀏覽器重新載入任何視窗或者窗體的情況下,指令碼實現web瀏覽器和伺服器之間的通訊。 ajax:為一種找早起避免頁面過載而動態更新頁面的方式,不過現在是直接資料驅動,或者類似於vue的單頁應用 comet:這個和ajax正好相反,為推送訊息到web瀏覽器端

ps;ajax和comet都為一個美國的洗滌日用品牌,╮(╯▽╰)╭

總說

網頁信標

img元素有一個src屬性,當指令碼設定img元素的src屬性,且把資訊作為圖片的url的查詢字串部分,即能把經過編碼的資訊椽筆給web伺服器,web伺服器實際上必須返回一個圖片作為結果。 事實上,使用一個空的js指令碼也可完成此操作 一個百度統計的js指令碼如下 (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請求數目,即可完成一次次的統計任務。使用者的頁面停留,直接計算兩次載入的時間差即可。資料庫完成統計即可。一個最簡單的頁面統計完成。

iframe

一個淘汰的標籤。 下面是舊的ajax方式 使用iframe完成一次ajax,指令碼先把要傳送給web伺服器的資訊編碼到url中,伺服器在動態的建立一個html文件,將其內容返回給web,在iframe中顯示,這種方式受道同源的限制。 上方的方式以及放棄。

script

通過script元素的src屬性設定url發起http get請求,即一種基於script的ajax傳輸,伺服器使用json編碼,執行指令碼的時候,將其轉碼,這種的ajax同時也稱為jsonp 即這種的跨域可以不受到同源的限制

ajax中的x

ajax中的x為xml為一種可選的通訊方式,也可以使用JSON完成通訊。

其他

一些更多的通訊協議,包括rpc(遠端過程呼叫)允許執行於一臺計算機的程式呼叫另一臺計算機程式的子程式。如果物件導向程式設計,則遠端過程呼叫為遠端呼叫,遠端方法呼叫。

釋出/訂閱事件系統

一種設計模式,有兩種,一種是觀察者模式,一種是釋出訂閱模式, 即,訊息推送使用的是釋出/訂閱事件系統

觀察者模式

意圖:定義物件間的一對多的依賴關係,當一個物件狀態發生改變時,所有依賴它的物件都得到通知,並進行更新 解決:一個物件狀態給其他物件通知的問題, 舉例應用:有個天氣中心的目標A,專門監聽天氣的變化,而有個顯示天氣的觀察者B,B把自己註冊到A裡,當A觸發天氣變化的時候,排程B更新方法,並帶上自己的上下文。 此處輸入圖片的描述

釋出/訂閱模式

訂閱者把自己想註冊的事件註冊到排程中心,當該事件觸發時,釋出者釋出事件到排程中心,由排程中心統一排程訂閱者註冊到排程中心的處理程式碼。 舉例:有個介面實時顯示天氣,它就訂閱天氣事件(註冊到排程中心),當天氣變化時定時獲取資料,作為釋出者到排程中心,排程中心排程訂閱者的天氣處理程式。 此處輸入圖片的描述

總結,區別

一個為點對點,一個為中間有一個過渡的,僅此而已。

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多元,書怎麼那麼貴呢。好貴,建議註冊一下

XMLHttpRequest

瀏覽器在CMLHttpRequest類上定義了其HTTP 的API 這個類的每個例項都表示一個獨立請求/響應對。並且這個物件屬性和方法允許指定請求細節和提取響應資料。

同java類似,使用這個api的第一件事例項化XMLHttpRequest物件

ps:能重用已存在的XMLHttpRequest 但是之前的物件將會被掛起

HTTP請求的4個部分

  1. http請求方法或者動作
  2. 正在請求的URL
  3. 一個可選的請求頭集合,其中可能包含身份驗證資訊
  4. 一個可選的請求主題

HTTP返回的響應

  1. 一個數字和文字組合成的狀態碼,如404(表示不存在)
  2. 一個響應頭集合
  3. 響應主體

為什麼本地不能直接使用ajax

在本地寫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()才方可。

一個栗子,通過post方法傳送純文字給伺服器

``` 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型別的更改

相關文章