天天看點

原生 JavaScript 實作 AJAX、JSONP

相信大多數前端開發者在需要與後端進行資料互動時,為了友善快捷,都會選擇​<code>​JQuery​</code>​中封裝的​<code>​AJAX​</code>​方法,但是有些時候,我們隻需要​<code>​JQuery​</code>​的​<code>​AJAX​</code>​請求方法,而其他的功能用到的很少,這顯然是沒必要的。 

其實,原生​<code>​JavaScript​</code>​實作​<code>​AJAX​</code>​并不難,這篇文章将會講解如何實作簡單的​<code>​AJAX​</code>​,還有跨域請求​<code>​JSONP​</code>​! 

一、AJAX 

AJAX的核心是​<code>​XMLHttpRequest​</code>​。 

一個完整的​<code>​AJAX​</code>​請求一般包括以下步驟:

執行個體化​<code>​XMLHttpRequest​</code>​對象

連接配接伺服器

發送請求

接收響應資料

我将​<code>​AJAX​</code>​請求封裝成​<code>​ajax()​</code>​方法,它接受一個配置對象​<code>​params​</code>​。

在上面的代碼中,已經添加具體的注釋,如需了解更多​<code>​AJAX​</code>​,可檢視部落客的書籍《 JavaScript半知半解》中的 ​<code>​AJAX​</code>​章節:AJAX 

使用執行個體:

二、JSONP 

同源政策 

AJAX之是以需要“跨域”,罪魁禍首就是浏覽器的 ​<code>​同源政策​</code>​。即,一個頁面的AJAX隻能擷取這個頁面相同源或者相同域的資料。 如何叫“同源”或者“同域”呢?——​<code>​協定、域名、端口号都必須相同​</code>​。例如:

當跨域請求時,一般都會看到這個錯誤: ​<code>​XMLHttpRequest cannot load http://ghmagical.com/article/?intro=jsonp%E8%AF%B7%E6%B1%82&amp;v=5520. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.​</code>​

那如何跨域請求呢?這時,JSONP就登場了! 

JSONP(JSON with Padding) 是一種跨域請求方式。主要原理是利用了​<code>​script ​</code>​标簽可以跨域請求的特性,由其 ​<code>​src​</code>​ 屬性發送請求到伺服器,伺服器傳回 ​<code>​JavaScript ​</code>​代碼,浏覽器接受響應,然後就直接執行了,這和通過 ​<code>​script​</code>​ 标簽引用外部檔案的原理是一樣的。

JSONP由兩部分組成:​<code>​回調函數​</code>​和​<code>​資料​</code>​,回調函數一般是在浏覽器控制,作為參數發往伺服器端(當然,你也可以固定回調函數的名字,但用戶端和伺服器端的名稱一定要一緻)。當伺服器響應時,伺服器端就會把該函數和資料拼成字元串傳回。 

JSONP的請求過程:

請求階段:浏覽器建立一個 ​<code>​script​</code>​ 标簽,并給其​<code>​src​</code>​ 指派(類似 ​<code>​http://example.com/api/?callback=jsonpCallback​</code>​ )。

發送請求:當給​<code>​script​</code>​的​<code>​src​</code>​指派時,浏覽器就會發起一個請求。

資料響應:服務端将要傳回的​<code>​資料​</code>​作為參數和​<code>​函數名稱​</code>​拼接在一起(格式類似”​<code>​jsonpCallback({name: 'abc'})​</code>​”)傳回。當浏覽器接收到了響應資料,由于發起請求的是 ​<code>​script​</code>​,是以相當于直接調用 ​<code>​jsonpCallback​</code>​ 方法,并且傳入了一個參數。

對于​<code>​JQuery​</code>​的JSONP請求,這裡就不多講了,之前也寫過一篇文章《JQuery的Ajax請求跨域問題》。 

在這裡講解一下用原生​<code>​JavaScript​</code>​如何實作。 

依舊是​<code>​ajax()​</code>​方法裡添加JSONP,後面會将兩者整合在一起,JSONP的配置參數主要多了一個​<code>​jsonp​</code>​參數,它就是你的回調函數名。

注意:因為 ​<code>​script​</code>​ 标簽的​<code>​ src​</code>​ 屬性隻在第一次設定的時候起作用,導緻 ​<code>​script​</code>​ 标簽沒法重用,是以每次完成操作之後要移除; 

在這裡背景使用PHP處理:

注意:别漏了用函數名與資料拼接傳回。 

當然,前面也說過,你可以給定固定回調函數名: