JavaScript詳細解析之網絡請求與遠程資源

本篇文章給大家帶來了關于javascript的相關知識 , 其中主要介紹了關于網絡請求與遠程資源的相關問題 , 包括了跨源資源共享、預檢請求、Fetch API等等內容 , 下面一起來看一下 , 希望對大家有幫助 。

JavaScript詳細解析之網絡請求與遠程資源

文章插圖

【相關推薦:javascript視頻教程、web前端】
一、Ajax的誕生2005年 , Jesse James Garrett撰寫了一篇文章《Ajax - A New Approach to Web Applications》 , 這篇文章中描繪了一個被稱為Ajax(Asynchronous JavaScript+XML , 即異步JavaScript+XML)的技術 。 這個技術涉及發送服務器請求額外數據而不刷新頁面 , 從而實現更好地用戶體驗 。 Garrett解釋了這個技術怎樣改變自Web誕生以來就一直延續的傳統單擊等待的模式 。
把Ajax推到歷史舞臺上的關鍵技術是XMLHttpRequest(XHR)對象 。 在XHR出現之前 , Ajax風格的通信必須通過一些黑科技實現 , 主要是使用隱藏的窗格或內嵌窗格 。 XHR為發送服務器請求和獲取相應提供了合理的接口 。 這個接口可以實現異步從服務器獲取額外數據 , 意味著用戶不用頁面刷新也可以獲取數據 。 通過XHR對象獲取數據后 , 可以使用DOM方法把數據插入網頁 。
XHR對象的API被普遍認為比較難用 , 而Fetch API自動誕生以后迅速成為了XHR更現代的替代標準 , Fetch API支持期約promise和服務線程(service worker) , 已經成為及其強大的Web開發工具 。
二、跨源資源共享通過XHR進行Ajax通信的一個主要限制是跨源安全策略 。 默認情況下 , XHR只能訪問與發起請求的頁面在同一域內的資源 。 這個安全限制可以防止某些惡意行為 。 不過 , 瀏覽器也需要支持合法跨源訪問的能力 。
跨源資源共享(CORS , Cross-Origin Rerource Sharing)定義了瀏覽器與服務器如何實現跨源通信 。 CORS背后的基本思路就是使用自定義的HTTP頭部允許瀏覽器和服務器相互了解 , 以確定請求或相應應該成功還是失敗 。
對于簡單的請求 , 比如GET或POST請求 , 沒有自定義頭部 , 而且請求體是text/plain類型 , 這樣的請求在發送時會有一個額外的頭部叫Origin 。 Origin頭部包含發送請求的頁面的源(協議、域名、端口) , 以便服務器確定是否為其提供響應 。
現代瀏覽器通過XMLHttpRequst對象原生支持CORS , 在嘗試訪問不同源的資源時 , 這個行為會被自動觸發 。 要向不同域的源發送請求 , 可以使用標準XHR對象并給open()方法傳入一個絕對URL , 比如:
let xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.reaponseText); }else{ alert("Request was unsuccessful:"+xhr.status); } }};xhr.open("get","http://www.nezha.con/page/",true);xhr.send(null);跨域XHR對象允許訪問status和statusText屬性 , 也允許同步請求 , 出于安全考慮 , 跨域XHR對象也施加了一些額外的限制 。
    不能使用setRequestHeader()設置自定義頭部;
    不能發送和接收cookie;
    getAllResponseHeaders()方法始終返回空字符串;
因為無論同域還是跨域請求都是用同一個接口 , 所以最好在訪問本地資源時使用相對URL , 在訪問遠程資源時使用絕對URL , 這樣可以更明確地區分使用場景 , 同時避免出現訪問本地資源時出現頭部或cookie信息訪問受限的問題 。
三、預檢請求CORS通過一種叫預檢請求的服務器驗證機制 , 允許使用自定義頭部、除GET和POST之外的方法 , 以及不同請求體內容類型 。 在要發送涉及上述某種高級選項的請求時 , 會先想服務器發送一個預檢請求 。 這個請求使用OPTIONS方法發送并包含如下頭部:
    Origin:與簡單請求相同;
    Access-Control-Request-Method:請求希望使用的方法;
    Access-Control-Request-Headers:(可選)要使用的逗號分隔的自定義頭部列表;
四、Fetch APIFetch API能夠執行XMLHttpRequest對象的所有任務 , 但更容易使用 , 接口也更現代化 , 能夠在Web工作線程等Web工具中使用 。 XMLHttpRequest可以選擇異步 , 而Fetch API則必須是異步 。
fetch()方法是暴露在全局作用域中的 , 包括主頁面執行線程、模塊和工作線程 。 調用這個方法 , 瀏覽器就會向給定URL發送請求 。
1、分派請求
fetch()只有一個必需的參數input 。 多數情況下 , 這個參數是獲取資源的URL , 這個方法返回一個期約:
let r = fetch('/bar');console.log(r);//Promise<pending>

推薦閱讀